Refactor how permissions are matched by ProjectControl, RefControl
AccessSections are now matched onto references using pre-compiled SectionMatcher objects. These matchers are built in the ProjectState on demand, and cached until the ProjectState itself is discarded from memory. This saves the Pattern.compile() costs, as well as some basic conditionals to determine which type of reference pattern the section uses, providing a small speed up to access rule evaluation. ProjectControl and RefControl now stores all permissions that belong to the project or reference, rather than only the ones relevant for their CurrentUser. This allows the control objects to provide cached data for other users, such as when ChangeControl needs to build a different copy of itself for each reviewer listed on the change. ProjectControl caches RefControls it builds, making it easier for callers like ReceiveCommits or VisibleRefFilter to deal with a lot of lookups for the same common reference name within a single project access request. This comes at a cost of memory, but should be an improvement in response time. Project ownership checks are now handled by ProjectState, relying on the cached localOwners data instead of looking at the OWNER permission on "refs/*". The cached localOwners is already built up from the "refs/*" data during ProjectState's constructor, so doing it dynamically via RefControl inside of ProjectControl was really quite wasteful. Change-Id: Iaf12bab55d41217363cc05ba024f452d03bc21df
This commit is contained in:
@@ -195,6 +195,21 @@ public class RefControlTest extends TestCase {
|
||||
u.controlForRef("refs/heads/master").canUpload());
|
||||
}
|
||||
|
||||
public void testUsernamePatternNonRegex() {
|
||||
grant(local, READ, devs, "refs/sb/${username}/heads/*");
|
||||
|
||||
ProjectControl u = user("u", devs), d = user("d", devs);
|
||||
assertFalse("u can't read", u.controlForRef("refs/sb/d/heads/foobar").isVisible());
|
||||
assertTrue("d can read", d.controlForRef("refs/sb/d/heads/foobar").isVisible());
|
||||
}
|
||||
|
||||
public void testUsernamePatternWithRegex() {
|
||||
grant(local, READ, devs, "^refs/sb/${username}/heads/.*");
|
||||
|
||||
ProjectControl u = user("d.v", devs), d = user("dev", devs);
|
||||
assertFalse("u can't read", u.controlForRef("refs/sb/dev/heads/foobar").isVisible());
|
||||
assertTrue("d can read", d.controlForRef("refs/sb/dev/heads/foobar").isVisible());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
@@ -307,19 +322,17 @@ public class RefControlTest extends TestCase {
|
||||
}
|
||||
|
||||
private ProjectControl user(AccountGroup.UUID... memberOf) {
|
||||
return user(null, memberOf);
|
||||
}
|
||||
|
||||
private ProjectControl user(String name, AccountGroup.UUID... memberOf) {
|
||||
SchemaFactory<ReviewDb> schema = null;
|
||||
GroupCache groupCache = null;
|
||||
String canonicalWebUrl = "http://localhost";
|
||||
|
||||
RefControl.Factory refControlFactory = new RefControl.Factory() {
|
||||
@Override
|
||||
public RefControl create(final ProjectControl projectControl, final String ref) {
|
||||
return new RefControl(projectControl, ref);
|
||||
}
|
||||
};
|
||||
return new ProjectControl(Collections.<AccountGroup.UUID> emptySet(),
|
||||
Collections.<AccountGroup.UUID> emptySet(), schema, groupCache,
|
||||
canonicalWebUrl, refControlFactory, new MockUser(memberOf),
|
||||
canonicalWebUrl, new MockUser(name, memberOf),
|
||||
newProjectState());
|
||||
}
|
||||
|
||||
@@ -338,10 +351,12 @@ public class RefControlTest extends TestCase {
|
||||
}
|
||||
|
||||
private class MockUser extends CurrentUser {
|
||||
private final String username;
|
||||
private final Set<AccountGroup.UUID> groups;
|
||||
|
||||
MockUser(AccountGroup.UUID[] groupId) {
|
||||
MockUser(String name, AccountGroup.UUID[] groupId) {
|
||||
super(RefControlTest.this.capabilityControlFactory, AccessPath.UNKNOWN);
|
||||
username = name;
|
||||
groups = new HashSet<AccountGroup.UUID>(Arrays.asList(groupId));
|
||||
groups.add(registered);
|
||||
groups.add(anonymous);
|
||||
@@ -352,6 +367,11 @@ public class RefControlTest extends TestCase {
|
||||
return groups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserName() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Change.Id> getStarredChanges() {
|
||||
return Collections.emptySet();
|
||||
|
||||
Reference in New Issue
Block a user