Added GroupMembership for group membership checks.

This replaces existing uses of a Set to determine membership and
will make it possible to integrate with group systems that do not
allow efficient enumentation of memberships.

Change-Id: Iba9842ca1a355fc100fb4a02d7954d89032cdba0
This commit is contained in:
Colby Ranger
2012-03-23 10:19:11 -07:00
parent 53f0f79da8
commit 05f2bc1c60
30 changed files with 329 additions and 127 deletions

View File

@@ -185,11 +185,6 @@ class SuggestServiceImpl extends BaseServiceImplementation implements
} }
} }
private Set<AccountGroup.UUID> groupsOf(Account account) {
IdentifiedUser user = userFactory.create(account.getId());
return new HashSet<AccountGroup.UUID>(user.getEffectiveGroups());
}
public void suggestAccountGroup(final String query, final int limit, public void suggestAccountGroup(final String query, final int limit,
final AsyncCallback<List<GroupReference>> callback) { final AsyncCallback<List<GroupReference>> callback) {
run(callback, new Action<List<GroupReference>>() { run(callback, new Action<List<GroupReference>>() {

View File

@@ -59,7 +59,7 @@ class AgreementInfoFactory extends Handler<AgreementInfo> {
final List<AccountGroupAgreement> groupAccepted = final List<AccountGroupAgreement> groupAccepted =
new ArrayList<AccountGroupAgreement>(); new ArrayList<AccountGroupAgreement>();
for (final AccountGroup.UUID groupUUID : user.getEffectiveGroups()) { for (final AccountGroup.UUID groupUUID : user.getEffectiveGroups().getKnownGroups()) {
AccountGroup group = groupCache.get(groupUUID); AccountGroup group = groupCache.get(groupUUID);
if (group == null) { if (group == null) {
continue; continue;

View File

@@ -36,8 +36,6 @@ import javax.servlet.ServletResponse;
/** /**
* Stores as a request attribute, so the {@link HttpLog} can include the the * Stores as a request attribute, so the {@link HttpLog} can include the the
* user for the request outside of the request scope. * user for the request outside of the request scope.
*
* @author cranger@google.com (Colby Ranger)
*/ */
@Singleton @Singleton
public class GetUserFilter implements Filter { public class GetUserFilter implements Filter {

View File

@@ -15,9 +15,6 @@
package com.google.gerrit.reviewdb.server; package com.google.gerrit.reviewdb.server;
import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroup.ExternalNameKey;
import com.google.gerrit.reviewdb.client.AccountGroup.Id;
import com.google.gerrit.reviewdb.client.AccountGroup.UUID;
import com.google.gwtorm.server.Access; import com.google.gwtorm.server.Access;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.PrimaryKey; import com.google.gwtorm.server.PrimaryKey;

View File

@@ -18,6 +18,8 @@ import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountProjectWatch; import com.google.gerrit.reviewdb.client.AccountProjectWatch;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.account.CapabilityControl; import com.google.gerrit.server.account.CapabilityControl;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.ListGroupMembership;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.util.Collection; import java.util.Collection;
@@ -32,8 +34,8 @@ public class AnonymousUser extends CurrentUser {
} }
@Override @Override
public Set<AccountGroup.UUID> getEffectiveGroups() { public GroupMembership getEffectiveGroups() {
return Collections.singleton(AccountGroup.ANONYMOUS_USERS); return new ListGroupMembership(Collections.singleton(AccountGroup.ANONYMOUS_USERS));
} }
@Override @Override

View File

@@ -14,10 +14,10 @@
package com.google.gerrit.server; package com.google.gerrit.server;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountProjectWatch; import com.google.gerrit.reviewdb.client.AccountProjectWatch;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.account.CapabilityControl; import com.google.gerrit.server.account.CapabilityControl;
import com.google.gerrit.server.account.GroupMembership;
import com.google.inject.servlet.RequestScoped; import com.google.inject.servlet.RequestScoped;
import java.util.Collection; import java.util.Collection;
@@ -60,7 +60,7 @@ public abstract class CurrentUser {
* *
* @return active groups for this user. * @return active groups for this user.
*/ */
public abstract Set<AccountGroup.UUID> getEffectiveGroups(); public abstract GroupMembership getEffectiveGroups();
/** Set of changes starred by this user. */ /** Set of changes starred by this user. */
public abstract Set<Change.Id> getStarredChanges(); public abstract Set<Change.Id> getStarredChanges();

View File

@@ -24,7 +24,8 @@ import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.AccountCache; import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountState; import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.CapabilityControl; import com.google.gerrit.server.account.CapabilityControl;
import com.google.gerrit.server.account.GroupIncludeCache; import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.MaterializedGroupMembership;
import com.google.gerrit.server.account.Realm; import com.google.gerrit.server.account.Realm;
import com.google.gerrit.server.config.AnonymousCowardName; import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.config.AuthConfig; import com.google.gerrit.server.config.AuthConfig;
@@ -52,9 +53,7 @@ import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Queue;
import java.util.Set; import java.util.Set;
import java.util.TimeZone; import java.util.TimeZone;
@@ -71,7 +70,7 @@ public class IdentifiedUser extends CurrentUser {
private final Provider<String> canonicalUrl; private final Provider<String> canonicalUrl;
private final Realm realm; private final Realm realm;
private final AccountCache accountCache; private final AccountCache accountCache;
private final GroupIncludeCache groupIncludeCache; private final MaterializedGroupMembership.Factory groupMembershipFactory;
@Inject @Inject
GenericFactory( GenericFactory(
@@ -80,14 +79,14 @@ public class IdentifiedUser extends CurrentUser {
final @AnonymousCowardName String anonymousCowardName, final @AnonymousCowardName String anonymousCowardName,
final @CanonicalWebUrl Provider<String> canonicalUrl, final @CanonicalWebUrl Provider<String> canonicalUrl,
final Realm realm, final AccountCache accountCache, final Realm realm, final AccountCache accountCache,
final GroupIncludeCache groupIncludeCache) { final MaterializedGroupMembership.Factory groupMembershipFactory) {
this.capabilityControlFactory = capabilityControlFactory; this.capabilityControlFactory = capabilityControlFactory;
this.authConfig = authConfig; this.authConfig = authConfig;
this.anonymousCowardName = anonymousCowardName; this.anonymousCowardName = anonymousCowardName;
this.canonicalUrl = canonicalUrl; this.canonicalUrl = canonicalUrl;
this.realm = realm; this.realm = realm;
this.accountCache = accountCache; this.accountCache = accountCache;
this.groupIncludeCache = groupIncludeCache; this.groupMembershipFactory = groupMembershipFactory;
} }
public IdentifiedUser create(final Account.Id id) { public IdentifiedUser create(final Account.Id id) {
@@ -97,14 +96,14 @@ public class IdentifiedUser extends CurrentUser {
public IdentifiedUser create(Provider<ReviewDb> db, Account.Id id) { public IdentifiedUser create(Provider<ReviewDb> db, Account.Id id) {
return new IdentifiedUser(capabilityControlFactory, AccessPath.UNKNOWN, return new IdentifiedUser(capabilityControlFactory, AccessPath.UNKNOWN,
authConfig, anonymousCowardName, canonicalUrl, realm, accountCache, authConfig, anonymousCowardName, canonicalUrl, realm, accountCache,
groupIncludeCache, null, db, id); groupMembershipFactory, null, db, id);
} }
public IdentifiedUser create(AccessPath accessPath, public IdentifiedUser create(AccessPath accessPath,
Provider<SocketAddress> remotePeerProvider, Account.Id id) { Provider<SocketAddress> remotePeerProvider, Account.Id id) {
return new IdentifiedUser(capabilityControlFactory, accessPath, return new IdentifiedUser(capabilityControlFactory, accessPath,
authConfig, anonymousCowardName, canonicalUrl, realm, accountCache, authConfig, anonymousCowardName, canonicalUrl, realm, accountCache,
groupIncludeCache, remotePeerProvider, null, id); groupMembershipFactory, remotePeerProvider, null, id);
} }
} }
@@ -122,7 +121,7 @@ public class IdentifiedUser extends CurrentUser {
private final Provider<String> canonicalUrl; private final Provider<String> canonicalUrl;
private final Realm realm; private final Realm realm;
private final AccountCache accountCache; private final AccountCache accountCache;
private final GroupIncludeCache groupIncludeCache; private final MaterializedGroupMembership.Factory groupMembershipFactory;
private final Provider<SocketAddress> remotePeerProvider; private final Provider<SocketAddress> remotePeerProvider;
private final Provider<ReviewDb> dbProvider; private final Provider<ReviewDb> dbProvider;
@@ -134,7 +133,7 @@ public class IdentifiedUser extends CurrentUser {
final @AnonymousCowardName String anonymousCowardName, final @AnonymousCowardName String anonymousCowardName,
final @CanonicalWebUrl Provider<String> canonicalUrl, final @CanonicalWebUrl Provider<String> canonicalUrl,
final Realm realm, final AccountCache accountCache, final Realm realm, final AccountCache accountCache,
final GroupIncludeCache groupIncludeCache, final MaterializedGroupMembership.Factory groupMembershipFactory,
final @RemotePeer Provider<SocketAddress> remotePeerProvider, final @RemotePeer Provider<SocketAddress> remotePeerProvider,
final Provider<ReviewDb> dbProvider) { final Provider<ReviewDb> dbProvider) {
@@ -144,7 +143,7 @@ public class IdentifiedUser extends CurrentUser {
this.canonicalUrl = canonicalUrl; this.canonicalUrl = canonicalUrl;
this.realm = realm; this.realm = realm;
this.accountCache = accountCache; this.accountCache = accountCache;
this.groupIncludeCache = groupIncludeCache; this.groupMembershipFactory = groupMembershipFactory;
this.remotePeerProvider = remotePeerProvider; this.remotePeerProvider = remotePeerProvider;
this.dbProvider = dbProvider; this.dbProvider = dbProvider;
@@ -154,7 +153,7 @@ public class IdentifiedUser extends CurrentUser {
final Account.Id id) { final Account.Id id) {
return new IdentifiedUser(capabilityControlFactory, accessPath, return new IdentifiedUser(capabilityControlFactory, accessPath,
authConfig, anonymousCowardName, canonicalUrl, realm, accountCache, authConfig, anonymousCowardName, canonicalUrl, realm, accountCache,
groupIncludeCache, remotePeerProvider, dbProvider, id); groupMembershipFactory, remotePeerProvider, dbProvider, id);
} }
} }
@@ -186,7 +185,7 @@ public class IdentifiedUser extends CurrentUser {
private final Provider<String> canonicalUrl; private final Provider<String> canonicalUrl;
private final Realm realm; private final Realm realm;
private final AccountCache accountCache; private final AccountCache accountCache;
private final GroupIncludeCache groupIncludeCache; private final MaterializedGroupMembership.Factory groupMembershipFactory;
private final AuthConfig authConfig; private final AuthConfig authConfig;
private final String anonymousCowardName; private final String anonymousCowardName;
@@ -200,7 +199,7 @@ public class IdentifiedUser extends CurrentUser {
private AccountState state; private AccountState state;
private Set<String> emailAddresses; private Set<String> emailAddresses;
private Set<AccountGroup.UUID> effectiveGroups; private GroupMembership effectiveGroups;
private Set<Change.Id> starredChanges; private Set<Change.Id> starredChanges;
private Collection<AccountProjectWatch> notificationFilters; private Collection<AccountProjectWatch> notificationFilters;
@@ -211,14 +210,14 @@ public class IdentifiedUser extends CurrentUser {
final String anonymousCowardName, final String anonymousCowardName,
final Provider<String> canonicalUrl, final Provider<String> canonicalUrl,
final Realm realm, final AccountCache accountCache, final Realm realm, final AccountCache accountCache,
final GroupIncludeCache groupIncludeCache, final MaterializedGroupMembership.Factory groupMembershipFactory,
@Nullable final Provider<SocketAddress> remotePeerProvider, @Nullable final Provider<SocketAddress> remotePeerProvider,
@Nullable final Provider<ReviewDb> dbProvider, final Account.Id id) { @Nullable final Provider<ReviewDb> dbProvider, final Account.Id id) {
super(capabilityControlFactory, accessPath); super(capabilityControlFactory, accessPath);
this.canonicalUrl = canonicalUrl; this.canonicalUrl = canonicalUrl;
this.realm = realm; this.realm = realm;
this.accountCache = accountCache; this.accountCache = accountCache;
this.groupIncludeCache = groupIncludeCache; this.groupMembershipFactory = groupMembershipFactory;
this.authConfig = authConfig; this.authConfig = authConfig;
this.anonymousCowardName = anonymousCowardName; this.anonymousCowardName = anonymousCowardName;
this.remotePeerProvider = remotePeerProvider; this.remotePeerProvider = remotePeerProvider;
@@ -270,39 +269,18 @@ public class IdentifiedUser extends CurrentUser {
} }
@Override @Override
public Set<AccountGroup.UUID> getEffectiveGroups() { public GroupMembership getEffectiveGroups() {
if (effectiveGroups == null) { if (effectiveGroups == null) {
Set<AccountGroup.UUID> seedGroups;
if (authConfig.isIdentityTrustable(state().getExternalIds())) { if (authConfig.isIdentityTrustable(state().getExternalIds())) {
seedGroups = realm.groups(state()); effectiveGroups = realm.groups(state());
} else { } else {
seedGroups = registeredGroups; effectiveGroups = groupMembershipFactory.create(registeredGroups);
} }
effectiveGroups = getIncludedGroups(seedGroups);
} }
return effectiveGroups; return effectiveGroups;
} }
private Set<AccountGroup.UUID> getIncludedGroups(Set<AccountGroup.UUID> seedGroups) {
Set<AccountGroup.UUID> includes = new HashSet<AccountGroup.UUID> (seedGroups);
Queue<AccountGroup.UUID> groupQueue = new LinkedList<AccountGroup.UUID> (seedGroups);
while (groupQueue.size() > 0) {
AccountGroup.UUID id = groupQueue.remove();
for (final AccountGroup.UUID groupId : groupIncludeCache.getByInclude(id)) {
if (includes.add(groupId)) {
groupQueue.add(groupId);
}
}
}
return Collections.unmodifiableSet(includes);
}
@Override @Override
public Set<Change.Id> getStarredChanges() { public Set<Change.Id> getStarredChanges() {
if (starredChanges == null) { if (starredChanges == null) {

View File

@@ -18,6 +18,7 @@ import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountProjectWatch; import com.google.gerrit.reviewdb.client.AccountProjectWatch;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.account.CapabilityControl; import com.google.gerrit.server.account.CapabilityControl;
import com.google.gerrit.server.account.GroupMembership;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
@@ -45,8 +46,8 @@ public class PeerDaemonUser extends CurrentUser {
} }
@Override @Override
public Set<AccountGroup.UUID> getEffectiveGroups() { public GroupMembership getEffectiveGroups() {
return Collections.emptySet(); return GroupMembership.EMPTY;
} }
@Override @Override

View File

@@ -18,47 +18,35 @@ import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountProjectWatch; import com.google.gerrit.reviewdb.client.AccountProjectWatch;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.account.CapabilityControl; import com.google.gerrit.server.account.CapabilityControl;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.ListGroupMembership;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.Set; import java.util.Set;
public class ReplicationUser extends CurrentUser { public class ReplicationUser extends CurrentUser {
/** Magic set of groups enabling read of any project and reference. */ /** Magic set of groups enabling read of any project and reference. */
public static final Set<AccountGroup.UUID> EVERYTHING_VISIBLE = public static final GroupMembership EVERYTHING_VISIBLE =
Collections.unmodifiableSet(new HashSet<AccountGroup.UUID>(0)); new ListGroupMembership(Collections.<AccountGroup.UUID>emptySet());
public interface Factory { public interface Factory {
ReplicationUser create(@Assisted Set<AccountGroup.UUID> authGroups); ReplicationUser create(@Assisted GroupMembership authGroups);
} }
private final Set<AccountGroup.UUID> effectiveGroups; private final GroupMembership effectiveGroups;
@Inject @Inject
protected ReplicationUser(CapabilityControl.Factory capabilityControlFactory, protected ReplicationUser(CapabilityControl.Factory capabilityControlFactory,
@Assisted Set<AccountGroup.UUID> authGroups) { @Assisted GroupMembership authGroups) {
super(capabilityControlFactory, AccessPath.REPLICATION); super(capabilityControlFactory, AccessPath.REPLICATION);
effectiveGroups = authGroups;
if (authGroups == EVERYTHING_VISIBLE) {
effectiveGroups = EVERYTHING_VISIBLE;
} else if (authGroups.isEmpty()) {
effectiveGroups = Collections.emptySet();
} else {
effectiveGroups = copy(authGroups);
}
}
private static Set<AccountGroup.UUID> copy(Set<AccountGroup.UUID> groups) {
return Collections.unmodifiableSet(new HashSet<AccountGroup.UUID>(groups));
} }
@Override @Override
public Set<AccountGroup.UUID> getEffectiveGroups() { public GroupMembership getEffectiveGroups() {
return effectiveGroups; return effectiveGroups;
} }

View File

@@ -80,11 +80,9 @@ public class AccountControl {
Set<AccountGroup.UUID> usersGroups = groupsOf(otherUser); Set<AccountGroup.UUID> usersGroups = groupsOf(otherUser);
usersGroups.remove(AccountGroup.ANONYMOUS_USERS); usersGroups.remove(AccountGroup.ANONYMOUS_USERS);
usersGroups.remove(AccountGroup.REGISTERED_USERS); usersGroups.remove(AccountGroup.REGISTERED_USERS);
for (AccountGroup.UUID myGroup : currentUser.getEffectiveGroups()) { if (currentUser.getEffectiveGroups().containsAnyOf(usersGroups)) {
if (usersGroups.contains(myGroup)) {
return true; return true;
} }
}
break; break;
} }
case VISIBLE_GROUP: { case VISIBLE_GROUP: {
@@ -111,7 +109,6 @@ public class AccountControl {
} }
private Set<AccountGroup.UUID> groupsOf(Account account) { private Set<AccountGroup.UUID> groupsOf(Account account) {
IdentifiedUser user = userFactory.create(account.getId()); return userFactory.create(account.getId()).getEffectiveGroups().getKnownGroups();
return new HashSet<AccountGroup.UUID>(user.getEffectiveGroups());
} }
} }

View File

@@ -14,6 +14,8 @@
package com.google.gerrit.server.account; package com.google.gerrit.server.account;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.gerrit.common.data.GlobalCapability; import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.GroupReference; import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.data.PermissionRange; import com.google.gerrit.common.data.PermissionRange;
@@ -31,7 +33,6 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** Access control management for server-wide capabilities. */ /** Access control management for server-wide capabilities. */
public class CapabilityControl { public class CapabilityControl {
@@ -129,7 +130,7 @@ public class CapabilityControl {
// the 'CI Servers' actually use the BATCH queue while everyone else gets // the 'CI Servers' actually use the BATCH queue while everyone else gets
// to use the INTERACTIVE queue without additional grants. // to use the INTERACTIVE queue without additional grants.
// //
Set<AccountGroup.UUID> groups = user.getEffectiveGroups(); GroupMembership groups = user.getEffectiveGroups();
boolean batch = false; boolean batch = false;
for (PermissionRule r : capabilities.priority) { for (PermissionRule r : capabilities.priority) {
if (match(groups, r)) { if (match(groups, r)) {
@@ -198,7 +199,7 @@ public class CapabilityControl {
return rules; return rules;
} }
Set<AccountGroup.UUID> groups = user.getEffectiveGroups(); GroupMembership groups = user.getEffectiveGroups();
if (rules.size() == 1) { if (rules.size() == 1) {
if (!match(groups, rules.get(0))) { if (!match(groups, rules.get(0))) {
rules = Collections.emptyList(); rules = Collections.emptyList();
@@ -222,16 +223,17 @@ public class CapabilityControl {
} }
private boolean matchAny(List<PermissionRule> rules) { private boolean matchAny(List<PermissionRule> rules) {
Set<AccountGroup.UUID> groups = user.getEffectiveGroups(); Iterable<AccountGroup.UUID> ids = Iterables.transform(rules,
for (PermissionRule rule : rules) { new Function<PermissionRule, AccountGroup.UUID>() {
if (match(groups, rule)) { @Override
return true; public AccountGroup.UUID apply(PermissionRule rule) {
return rule.getGroup().getUUID();
} }
} });
return false; return user.getEffectiveGroups().containsAnyOf(ids);
} }
private static boolean match(Set<AccountGroup.UUID> groups, private static boolean match(GroupMembership groups,
PermissionRule rule) { PermissionRule rule) {
return groups.contains(rule.getGroup().getUUID()); return groups.contains(rule.getGroup().getUUID());
} }

View File

@@ -20,17 +20,21 @@ import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Set; import java.util.Set;
public class DefaultRealm implements Realm { public class DefaultRealm implements Realm {
private final EmailExpander emailExpander; private final EmailExpander emailExpander;
private final AccountByEmailCache byEmail; private final AccountByEmailCache byEmail;
private final MaterializedGroupMembership.Factory groupMembershipFactory;
@Inject @Inject
DefaultRealm(final EmailExpander emailExpander, DefaultRealm(final EmailExpander emailExpander,
final AccountByEmailCache byEmail) { final AccountByEmailCache byEmail,
final MaterializedGroupMembership.Factory groupMembershipFactory) {
this.emailExpander = emailExpander; this.emailExpander = emailExpander;
this.byEmail = byEmail; this.byEmail = byEmail;
this.groupMembershipFactory = groupMembershipFactory;
} }
@Override @Override
@@ -57,8 +61,8 @@ public class DefaultRealm implements Realm {
} }
@Override @Override
public Set<AccountGroup.UUID> groups(final AccountState who) { public GroupMembership groups(final AccountState who) {
return who.getInternalGroups(); return groupMembershipFactory.create(who.getInternalGroups());
} }
@Override @Override

View File

@@ -0,0 +1,51 @@
// Copyright (C) 2012 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.account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import java.util.Collections;
import java.util.Set;
/**
* Implementations of GroupMembership provide methods to test
* the presence of a user in a particular group.
*/
public interface GroupMembership {
public static final GroupMembership EMPTY =
new ListGroupMembership(Collections.<AccountGroup.UUID>emptySet());
/**
* Returns {@code true} when the user this object was created for is a member
* of the specified group.
*/
boolean contains(AccountGroup.UUID groupId);
/**
* Returns {@code true} when the user this object was created for is a member
* of any of the specified group.
*/
boolean containsAnyOf(Iterable<AccountGroup.UUID> groupIds);
/**
* Returns the set of groups that can be determined by the implementation.
* This may not return all groups the {@link #contains(AccountGroup.UUID)}
* would return {@code true} for, but will at least contain all top level
* groups. This restriction stems from the API of some group systems, which
* make it expensive to enumate the members of a group.
*/
Set<AccountGroup.UUID> getKnownGroups();
}

View File

@@ -0,0 +1,52 @@
// Copyright (C) 2012 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.account;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.reviewdb.client.AccountGroup;
import java.util.Set;
/**
* GroupMembership over an explicit list.
*/
public class ListGroupMembership implements GroupMembership {
private final Set<AccountGroup.UUID> groups;
public ListGroupMembership(Iterable<AccountGroup.UUID> groupIds) {
this.groups = ImmutableSet.copyOf(groupIds);
}
@Override
public boolean contains(AccountGroup.UUID groupId) {
return groups.contains(groupId);
}
@Override
public boolean containsAnyOf(Iterable<AccountGroup.UUID> groupIds) {
for (AccountGroup.UUID groupId : groupIds) {
if (contains(groupId)) {
return true;
}
}
return false;
}
@Override
public Set<AccountGroup.UUID> getKnownGroups() {
return ImmutableSet.copyOf(groups);
}
}

View File

@@ -0,0 +1,93 @@
// Copyright (C) 2012 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.account;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.util.Collections;
import java.util.Queue;
import java.util.Set;
/**
* Creates a GroupMembership object from materialized collection of groups.
*/
public class MaterializedGroupMembership implements GroupMembership {
public interface Factory {
MaterializedGroupMembership create(Iterable<AccountGroup.UUID> groupIds);
}
private final GroupIncludeCache groupIncludeCache;
private final Set<AccountGroup.UUID> includes;
private final Queue<AccountGroup.UUID> groupQueue;
@Inject
MaterializedGroupMembership(
GroupIncludeCache groupIncludeCache,
@Assisted Iterable<AccountGroup.UUID> seedGroups) {
this.groupIncludeCache = groupIncludeCache;
this.includes = Sets.newHashSet(seedGroups);
this.groupQueue = Lists.newLinkedList(seedGroups);
}
@Override
public boolean contains(AccountGroup.UUID id) {
if (id == null) {
return false;
}
if (includes.contains(id)) {
return true;
}
return findIncludedGroup(Collections.singleton(id));
}
@Override
public boolean containsAnyOf(Iterable<AccountGroup.UUID> ids) {
Set<AccountGroup.UUID> query = Sets.newHashSet();
for (AccountGroup.UUID groupId : ids) {
if (includes.contains(groupId)) {
return true;
}
query.add(groupId);
}
return findIncludedGroup(query);
}
private boolean findIncludedGroup(Set<AccountGroup.UUID> query) {
boolean found = false;
while (!found && !groupQueue.isEmpty()) {
AccountGroup.UUID id = groupQueue.remove();
for (final AccountGroup.UUID groupId : groupIncludeCache.getByInclude(id)) {
if (includes.add(groupId)) {
groupQueue.add(groupId);
found |= query.contains(groupId);
}
}
}
return found;
}
@Override
public Set<AccountGroup.UUID> getKnownGroups() {
findIncludedGroup(Collections.<AccountGroup.UUID>emptySet()); // find all
return Sets.newHashSet(includes);
}
}

View File

@@ -31,7 +31,7 @@ public interface Realm {
public void onCreateAccount(AuthRequest who, Account account); public void onCreateAccount(AuthRequest who, Account account);
public Set<AccountGroup.UUID> groups(AccountState who); public GroupMembership groups(AccountState who);
/** /**
* Locate an account whose local username is the given account name. * Locate an account whose local username is the given account name.

View File

@@ -91,7 +91,8 @@ public class VisibleGroups {
NoSuchGroupException { NoSuchGroupException {
if (identifiedUser.get().getAccountId().equals(user.getAccountId()) if (identifiedUser.get().getAccountId().equals(user.getAccountId())
|| identifiedUser.get().getCapabilities().canAdministrateServer()) { || identifiedUser.get().getCapabilities().canAdministrateServer()) {
final Set<AccountGroup.UUID> effective = user.getEffectiveGroups(); final Set<AccountGroup.UUID> effective =
user.getEffectiveGroups().getKnownGroups();
final Set<AccountGroup> groups = final Set<AccountGroup> groups =
new TreeSet<AccountGroup>(new GroupComparator()); new TreeSet<AccountGroup>(new GroupComparator());
for (final AccountGroup.UUID groupId : effective) { for (final AccountGroup.UUID groupId : effective) {

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.server.auth.ldap;
import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_GERRIT; import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_GERRIT;
import com.google.common.collect.Iterables;
import com.google.gerrit.common.data.ParameterizedString; import com.google.gerrit.common.data.ParameterizedString;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountExternalId; import com.google.gerrit.reviewdb.client.AccountExternalId;
@@ -26,6 +27,8 @@ import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountState; import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.AuthRequest; import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.EmailExpander; import com.google.gerrit.server.account.EmailExpander;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.MaterializedGroupMembership;
import com.google.gerrit.server.account.Realm; import com.google.gerrit.server.account.Realm;
import com.google.gerrit.server.auth.AuthenticationUnavailableException; import com.google.gerrit.server.auth.AuthenticationUnavailableException;
import com.google.gerrit.server.auth.ldap.Helper.LdapSchema; import com.google.gerrit.server.auth.ldap.Helper.LdapSchema;
@@ -72,6 +75,7 @@ class LdapRealm implements Realm {
private final Config config; private final Config config;
private final Cache<String, Set<AccountGroup.UUID>> membershipCache; private final Cache<String, Set<AccountGroup.UUID>> membershipCache;
private final MaterializedGroupMembership.Factory groupMembershipFactory;
@Inject @Inject
LdapRealm( LdapRealm(
@@ -80,13 +84,15 @@ class LdapRealm implements Realm {
final EmailExpander emailExpander, final EmailExpander emailExpander,
@Named(LdapModule.GROUP_CACHE) final Cache<String, Set<AccountGroup.UUID>> membershipCache, @Named(LdapModule.GROUP_CACHE) final Cache<String, Set<AccountGroup.UUID>> membershipCache,
@Named(LdapModule.USERNAME_CACHE) final Cache<String, Account.Id> usernameCache, @Named(LdapModule.USERNAME_CACHE) final Cache<String, Account.Id> usernameCache,
@GerritServerConfig final Config config) { @GerritServerConfig final Config config,
final MaterializedGroupMembership.Factory groupMembershipFactory) {
this.helper = helper; this.helper = helper;
this.authConfig = authConfig; this.authConfig = authConfig;
this.emailExpander = emailExpander; this.emailExpander = emailExpander;
this.usernameCache = usernameCache; this.usernameCache = usernameCache;
this.membershipCache = membershipCache; this.membershipCache = membershipCache;
this.config = config; this.config = config;
this.groupMembershipFactory = groupMembershipFactory;
this.readOnlyAccountFields = new HashSet<Account.FieldName>(); this.readOnlyAccountFields = new HashSet<Account.FieldName>();
@@ -254,14 +260,12 @@ class LdapRealm implements Realm {
} }
@Override @Override
public Set<AccountGroup.UUID> groups(final AccountState who) { public GroupMembership groups(final AccountState who) {
final HashSet<AccountGroup.UUID> r = new HashSet<AccountGroup.UUID>(); return groupMembershipFactory.create(Iterables.concat(
r.addAll(membershipCache.get(findId(who.getExternalIds()))); membershipCache.get(findId(who.getExternalIds())),
r.addAll(who.getInternalGroups()); who.getInternalGroups()));
return r;
} }
private static String findId(final Collection<AccountExternalId> ids) { private static String findId(final Collection<AccountExternalId> ids) {
for (final AccountExternalId i : ids) { for (final AccountExternalId i : ids) {
if (i.isScheme(AccountExternalId.SCHEME_GERRIT)) { if (i.isScheme(AccountExternalId.SCHEME_GERRIT)) {

View File

@@ -19,6 +19,8 @@ import static org.eclipse.jgit.util.StringUtils.equalsIgnoreCase;
import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupName; import com.google.gerrit.reviewdb.client.AccountGroupName;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.ListGroupMembership;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory; import com.google.gwtorm.server.SchemaFactory;
@@ -310,7 +312,7 @@ public class ConfigUtil {
* @return the actual groups resolved from the database. If no groups are * @return the actual groups resolved from the database. If no groups are
* found, returns an empty {@code Set}, never {@code null}. * found, returns an empty {@code Set}, never {@code null}.
*/ */
public static Set<AccountGroup.UUID> groupsFor( public static GroupMembership groupsFor(
SchemaFactory<ReviewDb> dbfactory, String[] groupNames, Logger log, SchemaFactory<ReviewDb> dbfactory, String[] groupNames, Logger log,
String groupNotFoundWarning) { String groupNotFoundWarning) {
final Set<AccountGroup.UUID> result = new HashSet<AccountGroup.UUID>(); final Set<AccountGroup.UUID> result = new HashSet<AccountGroup.UUID>();
@@ -339,7 +341,7 @@ public class ConfigUtil {
} catch (OrmException e) { } catch (OrmException e) {
log.error("Database error, cannot load groups", e); log.error("Database error, cannot load groups", e);
} }
return result; return new ListGroupMembership(result);
} }
/** /**
@@ -352,7 +354,7 @@ public class ConfigUtil {
* @return the actual groups resolved from the database. If no groups are * @return the actual groups resolved from the database. If no groups are
* found, returns an empty {@code Set}, never {@code null}. * found, returns an empty {@code Set}, never {@code null}.
*/ */
public static Set<AccountGroup.UUID> groupsFor( public static GroupMembership groupsFor(
SchemaFactory<ReviewDb> dbfactory, String[] groupNames, Logger log) { SchemaFactory<ReviewDb> dbfactory, String[] groupNames, Logger log) {
return groupsFor(dbfactory, groupNames, log, return groupsFor(dbfactory, groupNames, log,
"Group \"{0}\" not in database, skipping."); "Group \"{0}\" not in database, skipping.");

View File

@@ -35,6 +35,7 @@ import com.google.gerrit.server.account.EmailExpander;
import com.google.gerrit.server.account.GroupCacheImpl; import com.google.gerrit.server.account.GroupCacheImpl;
import com.google.gerrit.server.account.GroupIncludeCacheImpl; import com.google.gerrit.server.account.GroupIncludeCacheImpl;
import com.google.gerrit.server.account.GroupInfoCacheFactory; import com.google.gerrit.server.account.GroupInfoCacheFactory;
import com.google.gerrit.server.account.MaterializedGroupMembership;
import com.google.gerrit.server.account.Realm; import com.google.gerrit.server.account.Realm;
import com.google.gerrit.server.auth.ldap.LdapModule; import com.google.gerrit.server.auth.ldap.LdapModule;
import com.google.gerrit.server.events.EventFactory; import com.google.gerrit.server.events.EventFactory;
@@ -118,6 +119,7 @@ public class GerritGlobalModule extends FactoryModule {
factory(CapabilityControl.Factory.class); factory(CapabilityControl.Factory.class);
factory(GroupInfoCacheFactory.Factory.class); factory(GroupInfoCacheFactory.Factory.class);
factory(ProjectState.Factory.class); factory(ProjectState.Factory.class);
factory(MaterializedGroupMembership.Factory.class);
bind(PermissionCollection.Factory.class); bind(PermissionCollection.Factory.class);
bind(AccountVisibility.class) bind(AccountVisibility.class)
.toProvider(AccountVisibilityProvider.class) .toProvider(AccountVisibilityProvider.class)

View File

@@ -40,7 +40,7 @@ public abstract class GroupSetProvider implements
protected GroupSetProvider(@GerritServerConfig Config config, protected GroupSetProvider(@GerritServerConfig Config config,
SchemaFactory<ReviewDb> db, String section, String subsection, String name) { SchemaFactory<ReviewDb> db, String section, String subsection, String name) {
String[] groupNames = config.getStringList(section, subsection, name); String[] groupNames = config.getStringList(section, subsection, name);
groupIds = unmodifiableSet(groupsFor(db, groupNames, log)); groupIds = unmodifiableSet(groupsFor(db, groupNames, log).getKnownGroups());
} }
@Override @Override

View File

@@ -19,6 +19,7 @@ import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.ReplicationUser; import com.google.gerrit.server.ReplicationUser;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.config.ConfigUtil; import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.FactoryModule; import com.google.gerrit.server.config.FactoryModule;
import com.google.gerrit.server.config.SitePaths; import com.google.gerrit.server.config.SitePaths;
@@ -404,7 +405,7 @@ public class PushReplication implements ReplicationQueue {
String[] authGroupNames = String[] authGroupNames =
cfg.getStringList("remote", rc.getName(), "authGroup"); cfg.getStringList("remote", rc.getName(), "authGroup");
final Set<AccountGroup.UUID> authGroups; final GroupMembership authGroups;
if (authGroupNames.length > 0) { if (authGroupNames.length > 0) {
authGroups = ConfigUtil.groupsFor(db, authGroupNames, // authGroups = ConfigUtil.groupsFor(db, authGroupNames, //
log, "Group \"{0}\" not in database, removing from authGroup"); log, "Group \"{0}\" not in database, removing from authGroup");

View File

@@ -70,7 +70,7 @@ public abstract class ChangeEmail extends OutgoingEmail {
/** Is the from user in an email squelching group? */ /** Is the from user in an email squelching group? */
final IdentifiedUser user = args.identifiedUserFactory.create(id); final IdentifiedUser user = args.identifiedUserFactory.create(id);
final Set<AccountGroup.UUID> gids = user.getEffectiveGroups(); final Set<AccountGroup.UUID> gids = user.getEffectiveGroups().getKnownGroups();
for (final AccountGroup.UUID gid : gids) { for (final AccountGroup.UUID gid : gids) {
AccountGroup group = args.groupCache.get(gid); AccountGroup group = args.groupCache.get(gid);
if (group != null && group.isEmailOnlyAuthors()) { if (group != null && group.isEmailOnlyAuthors()) {

View File

@@ -1,4 +1,16 @@
// Copyright 2012 Google Inc. All Rights Reserved. // Copyright (C) 2012 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.mail; package com.google.gerrit.server.mail;

View File

@@ -1,4 +1,16 @@
// Copyright 2012 Google Inc. All Rights Reserved. // Copyright (C) 2012 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.mail; package com.google.gerrit.server.mail;

View File

@@ -281,7 +281,7 @@ public class ProjectControl {
ContributorAgreement bestCla = null; ContributorAgreement bestCla = null;
try { try {
OUTER: for (AccountGroup.UUID groupUUID : iUser.getEffectiveGroups()) { OUTER: for (AccountGroup.UUID groupUUID : iUser.getEffectiveGroups().getKnownGroups()) {
AccountGroup group = groupCache.get(groupUUID); AccountGroup group = groupCache.get(groupUUID);
if (group == null) { if (group == null) {
continue; continue;

View File

@@ -25,6 +25,7 @@ import com.google.gerrit.rules.PrologEnvironment;
import com.google.gerrit.rules.RulesCache; import com.google.gerrit.rules.RulesCache;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.CapabilityCollection; import com.google.gerrit.server.account.CapabilityCollection;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.config.AllProjectsName; import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.ProjectConfig; import com.google.gerrit.server.git.ProjectConfig;
@@ -237,13 +238,13 @@ public class ProjectState {
* @return true if any of the groups listed in {@code groups} was declared to * @return true if any of the groups listed in {@code groups} was declared to
* be an owner of this project, or one of its parent projects.. * be an owner of this project, or one of its parent projects..
*/ */
boolean isOwner(Set<AccountGroup.UUID> groups) { boolean isOwner(GroupMembership groups) {
Set<Project.NameKey> seen = new HashSet<Project.NameKey>(); Set<Project.NameKey> seen = new HashSet<Project.NameKey>();
seen.add(getProject().getNameKey()); seen.add(getProject().getNameKey());
ProjectState s = this; ProjectState s = this;
do { do {
if (CollectionsUtil.isAnyIncludedIn(s.localOwners, groups)) { if (groups.containsAnyOf(s.localOwners)) {
return true; return true;
} }

View File

@@ -30,7 +30,7 @@ class IsVisibleToPredicate extends OperatorPredicate<ChangeData> {
return ((IdentifiedUser) user).getAccountId().toString(); return ((IdentifiedUser) user).getAccountId().toString();
} }
if (user instanceof SingleGroupUser) { if (user instanceof SingleGroupUser) {
return "group:" + ((SingleGroupUser) user).getEffectiveGroups() // return "group:" + ((SingleGroupUser) user).getEffectiveGroups().getKnownGroups() //
.iterator().next().toString(); .iterator().next().toString();
} }
return user.toString(); return user.toString();

View File

@@ -20,13 +20,15 @@ import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.AccessPath; import com.google.gerrit.server.AccessPath;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.CapabilityControl; import com.google.gerrit.server.account.CapabilityControl;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.ListGroupMembership;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
final class SingleGroupUser extends CurrentUser { final class SingleGroupUser extends CurrentUser {
private final Set<AccountGroup.UUID> groups; private final GroupMembership groups;
SingleGroupUser(CapabilityControl.Factory capabilityControlFactory, SingleGroupUser(CapabilityControl.Factory capabilityControlFactory,
AccountGroup.UUID groupId) { AccountGroup.UUID groupId) {
@@ -36,11 +38,11 @@ final class SingleGroupUser extends CurrentUser {
SingleGroupUser(CapabilityControl.Factory capabilityControlFactory, SingleGroupUser(CapabilityControl.Factory capabilityControlFactory,
Set<AccountGroup.UUID> groups) { Set<AccountGroup.UUID> groups) {
super(capabilityControlFactory, AccessPath.UNKNOWN); super(capabilityControlFactory, AccessPath.UNKNOWN);
this.groups = groups; this.groups = new ListGroupMembership(groups);
} }
@Override @Override
public Set<AccountGroup.UUID> getEffectiveGroups() { public GroupMembership getEffectiveGroups() {
return groups; return groups;
} }

View File

@@ -20,6 +20,9 @@ import static com.google.gerrit.common.data.Permission.PUSH;
import static com.google.gerrit.common.data.Permission.READ; import static com.google.gerrit.common.data.Permission.READ;
import static com.google.gerrit.common.data.Permission.SUBMIT; import static com.google.gerrit.common.data.Permission.SUBMIT;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gerrit.common.data.Capable; import com.google.gerrit.common.data.Capable;
import com.google.gerrit.common.data.GroupReference; import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.data.PermissionRange; import com.google.gerrit.common.data.PermissionRange;
@@ -35,6 +38,8 @@ import com.google.gerrit.server.AccessPath;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.CapabilityControl; import com.google.gerrit.server.account.CapabilityControl;
import com.google.gerrit.server.account.GroupCache; import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.ListGroupMembership;
import com.google.gerrit.server.cache.ConcurrentHashMapCache; import com.google.gerrit.server.cache.ConcurrentHashMapCache;
import com.google.gerrit.server.config.AllProjectsName; import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.FactoryModule; import com.google.gerrit.server.config.FactoryModule;
@@ -49,6 +54,7 @@ import junit.framework.TestCase;
import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Config;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -400,18 +406,19 @@ public class RefControlTest extends TestCase {
private class MockUser extends CurrentUser { private class MockUser extends CurrentUser {
private final String username; private final String username;
private final Set<AccountGroup.UUID> groups; private final GroupMembership groups;
MockUser(String name, AccountGroup.UUID[] groupId) { MockUser(String name, AccountGroup.UUID[] groupId) {
super(RefControlTest.this.capabilityControlFactory, AccessPath.UNKNOWN); super(RefControlTest.this.capabilityControlFactory, AccessPath.UNKNOWN);
username = name; username = name;
groups = new HashSet<AccountGroup.UUID>(Arrays.asList(groupId)); ArrayList<AccountGroup.UUID> groupIds = Lists.newArrayList(groupId);
groups.add(registered); groupIds.add(registered);
groups.add(anonymous); groupIds.add(anonymous);
groups = new ListGroupMembership(groupIds);
} }
@Override @Override
public Set<AccountGroup.UUID> getEffectiveGroups() { public GroupMembership getEffectiveGroups() {
return groups; return groups;
} }