Fix: permission on user specific reference name cannot work

In ExpandParameters.match() the parameter 'ref' may also contain
"${username}", e.g. in ProjectControl.canPerformOnAnyRef() the call
on controlForRef() puts in a access section name, in this case 'ref'
also need evaluation before doing next match, else it will not be
matched and that section is skipped in preparing RefControl.relevant,
as a result when a user has PUSH power *only* on that section, Gerrit
will reject any upload request from this user.

Fixed. evaluate any per-user ref in ExpandParameters.match().

Change-Id: I42c8e15d147eb4ad031b929cf51ccfc1e17a16e3
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 dcf6841..d882e0d 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
@@ -110,13 +110,24 @@
         u = username;
       }
 
-      RefPatternMatcher next =
-          getMatcher(template.replace(Collections.singletonMap("username", u)));
-      return next != null && next.match(ref, username);
+      RefPatternMatcher next = getMatcher(expand(template, u));
+      return next != null ? next.match(expand(ref, u), username) : false;
     }
 
     boolean matchPrefix(String ref) {
       return ref.startsWith(prefix);
     }
+
+    private String expand(String parameterizedRef, String userName) {
+      if (parameterizedRef.contains("${")) {
+        return expand(new ParameterizedString(parameterizedRef), userName);
+      }
+      return parameterizedRef;
+    }
+
+    private String expand(ParameterizedString parameterizedRef, String userName) {
+      return parameterizedRef.replace(Collections.singletonMap("username",
+          userName));
+    }
   }
 }
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 54765ac..74156dd 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
@@ -256,6 +256,13 @@
   }
 
   @Test
+  public void testUsernamePatternCanUploadToAnyRef() {
+    grant(local, PUSH, REGISTERED_USERS, "refs/heads/users/${username}/*");
+    ProjectControl u = util.user(local, "a-registered-user");
+    assertTrue("can upload", u.canPushToAtLeastOneRef() == Capable.OK);
+  }
+
+  @Test
   public void testUsernamePatternNonRegex() {
     grant(local, READ, DEVS, "refs/sb/${username}/heads/*");