From d3eb8fc937569599843cda0a7024d99402aee5f8 Mon Sep 17 00:00:00 2001 From: Edwin Kempin Date: Mon, 2 May 2016 13:53:41 +0200 Subject: [PATCH 1/3] Support fetch of refs/users/self from All-Users repository Allow a user to fetch its refs/users/YY/XXXXXXX branch as refs/users/self. The user branch contains the sharded account ID in the ref name, but this is an implementation detail that should be hidden from the user. On the other hand users should be able to access their user branch easily. Change-Id: I0f5a9f1456a86873ff91ad418aa60b1eee568109 Signed-off-by: Edwin Kempin --- .../acceptance/api/accounts/AccountIT.java | 26 +++++++++++++++++++ .../gerrit/reviewdb/client/RefNames.java | 3 +++ .../gerrit/server/git/VisibleRefFilter.java | 16 +++++++++++- .../gerrit/server/project/ProjectState.java | 8 ++++++ .../gerrit/server/project/RefControlTest.java | 11 +++++--- 5 files changed, 60 insertions(+), 4 deletions(-) diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java index e350cc9b7a..e62b2e9ade 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java @@ -17,6 +17,7 @@ package com.google.gerrit.acceptance.api.accounts; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assert_; +import static com.google.gerrit.acceptance.GitUtil.fetch; import static com.google.gerrit.gpg.PublicKeyStore.REFS_GPG_KEYS; import static com.google.gerrit.gpg.PublicKeyStore.keyToString; import static com.google.gerrit.gpg.testutil.TestKeys.allValidKeys; @@ -39,6 +40,7 @@ import com.google.gerrit.acceptance.TestAccount; import com.google.gerrit.extensions.api.accounts.EmailInput; import com.google.gerrit.extensions.api.changes.AddReviewerInput; import com.google.gerrit.extensions.api.changes.StarsInput; +import com.google.gerrit.extensions.client.GeneralPreferencesInfo; import com.google.gerrit.extensions.common.AccountInfo; import com.google.gerrit.extensions.common.ChangeInfo; import com.google.gerrit.extensions.common.GpgKeyInfo; @@ -53,6 +55,7 @@ import com.google.gerrit.gpg.server.GpgKeys; import com.google.gerrit.gpg.testutil.TestKey; import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.AccountExternalId; +import com.google.gerrit.reviewdb.client.RefNames; import com.google.gerrit.server.config.AllUsersName; import com.google.gerrit.testutil.ConfigSuite; import com.google.gerrit.testutil.FakeEmailSender.Message; @@ -62,6 +65,8 @@ import com.google.inject.Provider; import org.bouncycastle.bcpg.ArmoredOutputStream; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository; +import org.eclipse.jgit.junit.TestRepository; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefUpdate; @@ -354,6 +359,27 @@ public class AccountIT extends AbstractDaemonTest { gApi.accounts().self().addEmail(input); } + @Test + public void fetchUserBranch() throws Exception { + // change something in the user preferences to ensure that the user branch + // is created + GeneralPreferencesInfo input = new GeneralPreferencesInfo(); + input.changesPerPage = + GeneralPreferencesInfo.defaults().changesPerPage + 10; + gApi.accounts().self().setPreferences(input); + + TestRepository allUsersRepo = cloneProject(allUsers); + fetch(allUsersRepo, RefNames.refsUsers(admin.id) + ":userRef"); + Ref userRef = allUsersRepo.getRepository().exactRef("userRef"); + assertThat(userRef).isNotNull(); + + fetch(allUsersRepo, RefNames.REFS_USERS_SELF + ":userSelfRef"); + Ref userSelfRef = + allUsersRepo.getRepository().getRefDatabase().exactRef("userSelfRef"); + assertThat(userSelfRef).isNotNull(); + assertThat(userSelfRef.getObjectId()).isEqualTo(userRef.getObjectId()); + } + @Test public void addGpgKey() throws Exception { TestKey key = validKeyWithoutExpiration(); diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/RefNames.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/RefNames.java index d7c546b6ce..cd682d93e6 100644 --- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/RefNames.java +++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/RefNames.java @@ -33,6 +33,9 @@ public class RefNames { /** Preference settings for a user {@code refs/users} */ public static final String REFS_USERS = "refs/users/"; + /** Magic user branch in All-Users {@code refs/users/self} */ + public static final String REFS_USERS_SELF = "refs/users/self"; + /** Default user preference settings */ public static final String REFS_USERS_DEFAULT = RefNames.REFS_USERS + "default"; diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java index 9f2352a395..a53c49bf1d 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java @@ -29,6 +29,7 @@ import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.SymbolicRef; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.transport.AbstractAdvertiseRefsHook; import org.eclipse.jgit.transport.ServiceMayNotContinueException; @@ -69,6 +70,18 @@ public class VisibleRefFilter extends AbstractAdvertiseRefsHook { } public Map filter(Map refs, boolean filterTagsSeparately) { + if (projectCtl.getProjectState().isAllUsers() + && projectCtl.getUser().isIdentifiedUser()) { + Ref userRef = + refs.get(RefNames.refsUsers(projectCtl.getUser().getAccountId())); + if (userRef != null) { + SymbolicRef refsUsersSelf = + new SymbolicRef(RefNames.REFS_USERS_SELF, userRef); + refs = new HashMap<>(refs); + refs.put(refsUsersSelf.getName(), refsUsersSelf); + } + } + if (projectCtl.allRefsAreVisible(ImmutableSet.of(RefNames.REFS_CONFIG))) { Map r = Maps.newHashMap(refs); if (!projectCtl.controlForRef(RefNames.REFS_CONFIG).isVisible()) { @@ -97,7 +110,8 @@ public class VisibleRefFilter extends AbstractAdvertiseRefsHook { Account.Id accountId; if (ref.getName().startsWith(RefNames.REFS_CACHE_AUTOMERGE)) { continue; - } else if ((accountId = Account.Id.fromRef(ref.getName())) != null) { + } else if ((accountId = + Account.Id.fromRef(ref.getLeaf().getName())) != null) { // Reference related to an account is visible only for the current // account. // diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java index 28cb5b4d45..6343ed1969 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java @@ -38,6 +38,7 @@ import com.google.gerrit.rules.RulesCache; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.account.CapabilityCollection; import com.google.gerrit.server.config.AllProjectsName; +import com.google.gerrit.server.config.AllUsersName; import com.google.gerrit.server.config.SitePaths; import com.google.gerrit.server.git.BranchOrderSection; import com.google.gerrit.server.git.GitRepositoryManager; @@ -80,6 +81,7 @@ public class ProjectState { } private final boolean isAllProjects; + private final boolean isAllUsers; private final SitePaths sitePaths; private final AllProjectsName allProjectsName; private final ProjectCache projectCache; @@ -113,6 +115,7 @@ public class ProjectState { final SitePaths sitePaths, final ProjectCache projectCache, final AllProjectsName allProjectsName, + final AllUsersName allUsersName, final ProjectControl.AssistedFactory projectControlFactory, final PrologEnvironment.Factory envFactory, final GitRepositoryManager gitMgr, @@ -122,6 +125,7 @@ public class ProjectState { this.sitePaths = sitePaths; this.projectCache = projectCache; this.isAllProjects = config.getProject().getNameKey().equals(allProjectsName); + this.isAllUsers = config.getProject().getNameKey().equals(allUsersName); this.allProjectsName = allProjectsName; this.projectControlFactory = projectControlFactory; this.envFactory = envFactory; @@ -362,6 +366,10 @@ public class ProjectState { return isAllProjects; } + public boolean isAllUsers() { + return isAllUsers; + } + public boolean isUseContributorAgreements() { return getInheritableBoolean(new Function() { @Override diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java index 3ab2ff6d09..1e65560ba6 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java @@ -51,6 +51,8 @@ import com.google.gerrit.server.account.GroupMembership; import com.google.gerrit.server.account.ListGroupMembership; import com.google.gerrit.server.config.AllProjectsName; import com.google.gerrit.server.config.AllProjectsNameProvider; +import com.google.gerrit.server.config.AllUsersName; +import com.google.gerrit.server.config.AllUsersNameProvider; import com.google.gerrit.server.config.SitePaths; import com.google.gerrit.server.git.ProjectConfig; import com.google.gerrit.server.schema.SchemaCreator; @@ -218,6 +220,8 @@ public class RefControlTest { private final AllProjectsName allProjectsName = new AllProjectsName(AllProjectsNameProvider.DEFAULT); + private final AllUsersName allUsersName = + new AllUsersName(AllUsersNameProvider.DEFAULT); private final AccountGroup.UUID fixers = new AccountGroup.UUID("test.fixers"); private final Map all = new HashMap<>(); private Project.NameKey localKey = new Project.NameKey("local"); @@ -858,9 +862,10 @@ public class RefControlTest { } catch (IOException | ConfigInvalidException e) { throw new RuntimeException(e); } - all.put(pc.getName(), new ProjectState(sitePaths, - projectCache, allProjectsName, projectControlFactory, envFactory, - repoManager, rulesCache, commentLinks, pc)); + all.put(pc.getName(), + new ProjectState(sitePaths, projectCache, allProjectsName, allUsersName, + projectControlFactory, envFactory, repoManager, rulesCache, + commentLinks, pc)); return repo; } From 0940e12e38993cbc68a5e7850f6043cb790c450c Mon Sep 17 00:00:00 2001 From: Edwin Kempin Date: Thu, 28 Apr 2016 13:37:48 +0200 Subject: [PATCH 2/3] Support push to refs/users/self in All-Users repository Allow a user to push to its refs/users/YY/XXXXXXX branch as refs/users/self. The user branch contains the sharded account ID in the ref name, but this is an implementation detail that should be hidden from the user. On the other hand users should be able to push to their user branch easily. A user can also push a commit on its user branch for review by pushing to refs/for/refs/users/self. Change-Id: I4883cb13d77ef181896d2f1f7c4c234994a1f24a Signed-off-by: Edwin Kempin --- .../acceptance/api/accounts/AccountIT.java | 60 +++++++++++++++++++ .../gerrit/server/git/ReceiveCommits.java | 19 +++++- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java index e62b2e9ade..2d3f98a962 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java @@ -37,6 +37,7 @@ import com.google.gerrit.acceptance.AbstractDaemonTest; import com.google.gerrit.acceptance.AccountCreator; import com.google.gerrit.acceptance.PushOneCommit; import com.google.gerrit.acceptance.TestAccount; +import com.google.gerrit.common.data.Permission; import com.google.gerrit.extensions.api.accounts.EmailInput; import com.google.gerrit.extensions.api.changes.AddReviewerInput; import com.google.gerrit.extensions.api.changes.StarsInput; @@ -57,6 +58,8 @@ import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.AccountExternalId; import com.google.gerrit.reviewdb.client.RefNames; import com.google.gerrit.server.config.AllUsersName; +import com.google.gerrit.server.git.ProjectConfig; +import com.google.gerrit.server.util.MagicBranch; import com.google.gerrit.testutil.ConfigSuite; import com.google.gerrit.testutil.FakeEmailSender.Message; import com.google.inject.Inject; @@ -380,6 +383,63 @@ public class AccountIT extends AbstractDaemonTest { assertThat(userSelfRef.getObjectId()).isEqualTo(userRef.getObjectId()); } + @Test + public void pushToUserBranch() throws Exception { + // change something in the user preferences to ensure that the user branch + // is created + GeneralPreferencesInfo input = new GeneralPreferencesInfo(); + input.changesPerPage = + GeneralPreferencesInfo.defaults().changesPerPage + 10; + gApi.accounts().self().setPreferences(input); + + removeExclusiveReadPermissionOnAllUsers(); + String userRefName = RefNames.refsUsers(admin.id); + grant(Permission.PUSH, allUsers, userRefName); + + TestRepository allUsersRepo = cloneProject(allUsers); + fetch(allUsersRepo, RefNames.refsUsers(admin.id) + ":userRef"); + allUsersRepo.reset("userRef"); + PushOneCommit push = pushFactory.create(db, admin.getIdent(), allUsersRepo); + push.to(userRefName).assertOkStatus(); + + push = pushFactory.create(db, admin.getIdent(), allUsersRepo); + push.to(RefNames.REFS_USERS_SELF).assertOkStatus(); + } + + @Test + public void pushToUserBranchForReview() throws Exception { + // change something in the user preferences to ensure that the user branch + // is created + GeneralPreferencesInfo input = new GeneralPreferencesInfo(); + input.changesPerPage = + GeneralPreferencesInfo.defaults().changesPerPage + 10; + gApi.accounts().self().setPreferences(input); + + removeExclusiveReadPermissionOnAllUsers(); + String userRefName = RefNames.refsUsers(admin.id); + grant(Permission.PUSH, allUsers, MagicBranch.NEW_CHANGE + userRefName); + + TestRepository allUsersRepo = cloneProject(allUsers); + fetch(allUsersRepo, RefNames.refsUsers(admin.id) + ":userRef"); + allUsersRepo.reset("userRef"); + PushOneCommit push = pushFactory.create(db, admin.getIdent(), allUsersRepo); + PushOneCommit.Result r = push.to(MagicBranch.NEW_CHANGE + userRefName); + r.assertOkStatus(); + assertThat(r.getChange().change().getDest().get()).isEqualTo(userRefName); + + push = pushFactory.create(db, admin.getIdent(), allUsersRepo); + r = push.to(MagicBranch.NEW_CHANGE + RefNames.REFS_USERS_SELF); + r.assertOkStatus(); + assertThat(r.getChange().change().getDest().get()).isEqualTo(userRefName); + } + + private void removeExclusiveReadPermissionOnAllUsers() throws Exception { + ProjectConfig cfg = projectCache.checkedGet(allUsers).getConfig(); + cfg.getAccessSection(RefNames.REFS_USERS + "*", true) + .remove(new Permission(Permission.READ)); + saveProjectConfig(allUsers, cfg); + } + @Test public void addGpgKey() throws Exception { TestKey key = validKeyWithoutExpiration(); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java index b52844d923..f7c2dcc4bb 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java @@ -632,7 +632,7 @@ public class ReceiveCommits { } Set branches = new HashSet<>(); - for (ReceiveCommand c : commands) { + for (ReceiveCommand c : batch.getCommands()) { if (c.getResult() == OK) { if (c.getType() == ReceiveCommand.Type.UPDATE) { // aka fast-forward tagCache.updateFastForward(project.getNameKey(), @@ -890,6 +890,19 @@ public class ReceiveCommits { continue; } + if (projectControl.getProjectState().isAllUsers() + && RefNames.REFS_USERS_SELF.equals(cmd.getRefName())) { + final ReceiveCommand orgCmd = cmd; + cmd = new ReceiveCommand(cmd.getOldId(), cmd.getNewId(), + RefNames.refsUsers(user.getAccountId()), cmd.getType()) { + @Override + public void setResult(Result s, String m) { + super.setResult(s, m); + orgCmd.setResult(s, m); + } + }; + } + Matcher m = NEW_PATCHSET.matcher(cmd.getRefName()); if (m.matches()) { // The referenced change must exist and must still be open. @@ -1303,6 +1316,10 @@ public class ReceiveCommits { reject(cmd, "see help"); return; } + if (projectControl.getProjectState().isAllUsers() + && RefNames.REFS_USERS_SELF.equals(ref)) { + ref = RefNames.refsUsers(user.getAccountId()); + } if (!rp.getAdvertisedRefs().containsKey(ref) && !ref.equals(readHEAD(repo))) { if (ref.startsWith(Constants.R_HEADS)) { String n = ref.substring(Constants.R_HEADS.length()); From 60a0c991ca1b952638a5c9a302cdbb4a57352c69 Mon Sep 17 00:00:00 2001 From: Edwin Kempin Date: Mon, 2 May 2016 15:27:01 +0200 Subject: [PATCH 3/3] 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 --- .../gerrit/server/project/ChangeControl.java | 2 +- .../server/project/PermissionCollection.java | 25 ++++----- .../gerrit/server/project/ProjectControl.java | 19 +------ .../server/project/RefPatternMatcher.java | 53 ++++++++++++++----- .../gerrit/server/project/SectionMatcher.java | 5 +- 5 files changed, 53 insertions(+), 51 deletions(-) diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java index 62c6d5e9eb..0c74ca8249 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java @@ -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) { diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PermissionCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PermissionCollection.java index 9a9c5bb7e8..ee6fac72b2 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/PermissionCollection.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PermissionCollection.java @@ -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 matcherList, - String ref, Provider> usernameProvider) { + String ref, CurrentUser user) { if (isRE(ref)) { ref = RefControl.shortestExample(ref); } else if (ref.endsWith("/*")) { ref = ref.substring(0, ref.length() - 1); } - Collection usernames = null; boolean perUser = false; Map 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); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java index 6fab775d68..93aec5c306 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java @@ -227,25 +227,8 @@ public class ProjectControl { } RefControl ctl = refControls.get(refName); if (ctl == null) { - Provider> usernames = new Provider>() { - @Override - public List get() { - List r; - if (user.isIdentifiedUser()) { - Set 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); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefPatternMatcher.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefPatternMatcher.java index d80323fd4e..96b9e10254 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefPatternMatcher.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefPatternMatcher.java @@ -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 getUsernames(CurrentUser user) { + if (user.isIdentifiedUser()) { + Set 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) { diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SectionMatcher.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SectionMatcher.java index 4d1688f0f7..67b34a6b0e 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/SectionMatcher.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SectionMatcher.java @@ -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); } }