Added support for included groups
This change adds a new item to the group configuration: a list of groups whose members should be included in this one. This makes it possible to set up a hierarchy of included groups, which can make it easier to maintain complex access control lists. To accomplish this, two new database tables were added, called AccountGroupIncludes and AccountGroupIncludesAudit. The relevant support code was added around them, largely based on the existing code for handling indivdual account membership. In addition, caches for group information were added, paralleling the caches that already exist for accounts. Change-Id: Ib6990c17739f28f38bc13961143db7ce79251567
This commit is contained in:
committed by
Shawn O. Pearce
parent
0860e1b13c
commit
620255aef7
@@ -23,6 +23,7 @@ import com.google.gerrit.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.reviewdb.StarredChange;
|
||||
import com.google.gerrit.server.account.AccountCache;
|
||||
import com.google.gerrit.server.account.AccountState;
|
||||
import com.google.gerrit.server.account.GroupIncludeCache;
|
||||
import com.google.gerrit.server.account.Realm;
|
||||
import com.google.gerrit.server.config.AuthConfig;
|
||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||
@@ -46,7 +47,9 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@@ -61,15 +64,18 @@ public class IdentifiedUser extends CurrentUser {
|
||||
private final Provider<String> canonicalUrl;
|
||||
private final Realm realm;
|
||||
private final AccountCache accountCache;
|
||||
private final GroupIncludeCache groupIncludeCache;
|
||||
|
||||
@Inject
|
||||
GenericFactory(final AuthConfig authConfig,
|
||||
final @CanonicalWebUrl Provider<String> canonicalUrl,
|
||||
final Realm realm, final AccountCache accountCache) {
|
||||
final Realm realm, final AccountCache accountCache,
|
||||
final GroupIncludeCache groupIncludeCache) {
|
||||
this.authConfig = authConfig;
|
||||
this.canonicalUrl = canonicalUrl;
|
||||
this.realm = realm;
|
||||
this.accountCache = accountCache;
|
||||
this.groupIncludeCache = groupIncludeCache;
|
||||
}
|
||||
|
||||
public IdentifiedUser create(final Account.Id id) {
|
||||
@@ -78,13 +84,13 @@ public class IdentifiedUser extends CurrentUser {
|
||||
|
||||
public IdentifiedUser create(Provider<ReviewDb> db, Account.Id id) {
|
||||
return new IdentifiedUser(AccessPath.UNKNOWN, authConfig, canonicalUrl,
|
||||
realm, accountCache, null, db, id);
|
||||
realm, accountCache, groupIncludeCache, null, db, id);
|
||||
}
|
||||
|
||||
public IdentifiedUser create(AccessPath accessPath,
|
||||
Provider<SocketAddress> remotePeerProvider, Account.Id id) {
|
||||
return new IdentifiedUser(accessPath, authConfig, canonicalUrl, realm,
|
||||
accountCache, remotePeerProvider, null, id);
|
||||
accountCache, groupIncludeCache, remotePeerProvider, null, id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +106,7 @@ public class IdentifiedUser extends CurrentUser {
|
||||
private final Provider<String> canonicalUrl;
|
||||
private final Realm realm;
|
||||
private final AccountCache accountCache;
|
||||
private final GroupIncludeCache groupIncludeCache;
|
||||
|
||||
private final Provider<SocketAddress> remotePeerProvider;
|
||||
private final Provider<ReviewDb> dbProvider;
|
||||
@@ -108,6 +115,7 @@ public class IdentifiedUser extends CurrentUser {
|
||||
RequestFactory(final AuthConfig authConfig,
|
||||
final @CanonicalWebUrl Provider<String> canonicalUrl,
|
||||
final Realm realm, final AccountCache accountCache,
|
||||
final GroupIncludeCache groupIncludeCache,
|
||||
|
||||
final @RemotePeer Provider<SocketAddress> remotePeerProvider,
|
||||
final Provider<ReviewDb> dbProvider) {
|
||||
@@ -115,6 +123,7 @@ public class IdentifiedUser extends CurrentUser {
|
||||
this.canonicalUrl = canonicalUrl;
|
||||
this.realm = realm;
|
||||
this.accountCache = accountCache;
|
||||
this.groupIncludeCache = groupIncludeCache;
|
||||
|
||||
this.remotePeerProvider = remotePeerProvider;
|
||||
this.dbProvider = dbProvider;
|
||||
@@ -123,7 +132,7 @@ public class IdentifiedUser extends CurrentUser {
|
||||
public IdentifiedUser create(final AccessPath accessPath,
|
||||
final Account.Id id) {
|
||||
return new IdentifiedUser(accessPath, authConfig, canonicalUrl, realm,
|
||||
accountCache, remotePeerProvider, dbProvider, id);
|
||||
accountCache, groupIncludeCache, remotePeerProvider, dbProvider, id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +142,7 @@ public class IdentifiedUser extends CurrentUser {
|
||||
private final Provider<String> canonicalUrl;
|
||||
private final Realm realm;
|
||||
private final AccountCache accountCache;
|
||||
private final GroupIncludeCache groupIncludeCache;
|
||||
|
||||
@Nullable
|
||||
private final Provider<SocketAddress> remotePeerProvider;
|
||||
@@ -151,12 +161,14 @@ public class IdentifiedUser extends CurrentUser {
|
||||
private IdentifiedUser(final AccessPath accessPath,
|
||||
final AuthConfig authConfig, final Provider<String> canonicalUrl,
|
||||
final Realm realm, final AccountCache accountCache,
|
||||
final GroupIncludeCache groupIncludeCache,
|
||||
@Nullable final Provider<SocketAddress> remotePeerProvider,
|
||||
@Nullable final Provider<ReviewDb> dbProvider, final Account.Id id) {
|
||||
super(accessPath, authConfig);
|
||||
this.canonicalUrl = canonicalUrl;
|
||||
this.realm = realm;
|
||||
this.accountCache = accountCache;
|
||||
this.groupIncludeCache = groupIncludeCache;
|
||||
this.remotePeerProvider = remotePeerProvider;
|
||||
this.dbProvider = dbProvider;
|
||||
this.accountId = id;
|
||||
@@ -207,14 +219,35 @@ public class IdentifiedUser extends CurrentUser {
|
||||
@Override
|
||||
public Set<AccountGroup.Id> getEffectiveGroups() {
|
||||
if (effectiveGroups == null) {
|
||||
if (authConfig.isIdentityTrustable(state().getExternalIds())) {
|
||||
effectiveGroups = realm.groups(state());
|
||||
Set<AccountGroup.Id> seedGroups;
|
||||
|
||||
if (authConfig.isIdentityTrustable(state().getExternalIds())) {
|
||||
seedGroups = realm.groups(state());
|
||||
} else {
|
||||
effectiveGroups = authConfig.getRegisteredGroups();
|
||||
seedGroups = authConfig.getRegisteredGroups();
|
||||
}
|
||||
|
||||
effectiveGroups = getIncludedGroups(seedGroups);
|
||||
}
|
||||
|
||||
return effectiveGroups;
|
||||
}
|
||||
|
||||
private Set<AccountGroup.Id> getIncludedGroups(Set<AccountGroup.Id> seedGroups) {
|
||||
Set<AccountGroup.Id> includes = new HashSet<AccountGroup.Id> (seedGroups);
|
||||
Queue<AccountGroup.Id> groupQueue = new LinkedList<AccountGroup.Id> (seedGroups);
|
||||
|
||||
while (groupQueue.size() > 0) {
|
||||
AccountGroup.Id id = groupQueue.remove();
|
||||
|
||||
for (final AccountGroup.Id groupId : groupIncludeCache.getByInclude(id)) {
|
||||
if (includes.add(groupId)) {
|
||||
groupQueue.add(groupId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return effectiveGroups;
|
||||
|
||||
return Collections.unmodifiableSet(includes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user