Use AccountGroup.UUID instead of Account.Id

By switching to the UUID we can have a globally unique identifier
for group membership throughout the server, even if group information
comes in from a different data source.

Change-Id: Icb49d6a6aff8e62864ac0f78ceedbe03f01de894
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2010-12-21 12:33:12 -08:00
parent bcc191c020
commit e662fb3d4d
49 changed files with 374 additions and 229 deletions

View File

@@ -20,7 +20,6 @@ import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.AccountExternalId;
import com.google.gerrit.reviewdb.AccountGroup;
import com.google.gerrit.reviewdb.AccountGroup.Id;
import com.google.gerrit.reviewdb.AccountGroupName;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.ReviewDb;
@@ -158,10 +157,11 @@ class SuggestServiceImpl extends BaseServiceImplementation implements
map.put(account.getId(), info);
break;
case SAME_GROUP: {
Set<AccountGroup.Id> usersGroups = groupsOf(account);
usersGroups.removeAll(authConfig.getRegisteredGroups());
Set<AccountGroup.UUID> usersGroups = groupsOf(account);
usersGroups.remove(AccountGroup.ANONYMOUS_USERS);
usersGroups.remove(AccountGroup.REGISTERED_USERS);
usersGroups.remove(authConfig.getBatchUsersGroup());
for (AccountGroup.Id myGroup : currentUser.get().getEffectiveGroups()) {
for (AccountGroup.UUID myGroup : currentUser.get().getEffectiveGroups()) {
if (usersGroups.contains(myGroup)) {
map.put(account.getId(), info);
break;
@@ -176,9 +176,9 @@ class SuggestServiceImpl extends BaseServiceImplementation implements
}
}
private Set<Id> groupsOf(Account account) {
private Set<AccountGroup.UUID> groupsOf(Account account) {
IdentifiedUser user = userFactory.create(account.getId());
return new HashSet<AccountGroup.Id>(user.getEffectiveGroups());
return new HashSet<AccountGroup.UUID>(user.getEffectiveGroups());
}
public void suggestAccountGroup(final String query, final int limit,
@@ -189,7 +189,7 @@ class SuggestServiceImpl extends BaseServiceImplementation implements
final String b = a + MAX_SUFFIX;
final int max = 10;
final int n = limit <= 0 ? max : Math.min(limit, max);
Set<AccountGroup.Id> memberOf = currentUser.get().getEffectiveGroups();
Set<AccountGroup.UUID> memberOf = currentUser.get().getEffectiveGroups();
List<AccountGroupName> names = new ArrayList<AccountGroupName>(n);
for (AccountGroupName group : db.accountGroupNames()
.suggestByName(a, b, n)) {

View File

@@ -22,6 +22,7 @@ import com.google.gerrit.reviewdb.AccountGroupAgreement;
import com.google.gerrit.reviewdb.ContributorAgreement;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.GroupCache;
import com.google.inject.Inject;
import java.util.ArrayList;
@@ -36,13 +37,16 @@ class AgreementInfoFactory extends Handler<AgreementInfo> {
}
private final ReviewDb db;
private final GroupCache groupCache;
private final IdentifiedUser user;
private AgreementInfo info;
@Inject
AgreementInfoFactory(final ReviewDb db, final IdentifiedUser user) {
AgreementInfoFactory(final ReviewDb db, final GroupCache groupCache,
final IdentifiedUser user) {
this.db = db;
this.groupCache = groupCache;
this.user = user;
}
@@ -55,9 +59,14 @@ class AgreementInfoFactory extends Handler<AgreementInfo> {
final List<AccountGroupAgreement> groupAccepted =
new ArrayList<AccountGroupAgreement>();
for (final AccountGroup.Id groupId : user.getEffectiveGroups()) {
for (final AccountGroup.UUID groupUUID : user.getEffectiveGroups()) {
AccountGroup group = groupCache.get(groupUUID);
if (group == null) {
continue;
}
final List<AccountGroupAgreement> temp =
db.accountGroupAgreements().byGroup(groupId).toList();
db.accountGroupAgreements().byGroup(group.getId()).toList();
Collections.reverse(temp);

View File

@@ -46,6 +46,7 @@ import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -281,7 +282,7 @@ class GroupAdminServiceImpl extends BaseServiceImplementation implements
Collections.singleton(new AccountGroupIncludeAudit(m,
getAccountId())));
db.accountGroupIncludes().insert(Collections.singleton(m));
groupIncludeCache.evictInclude(a.getId());
groupIncludeCache.evictInclude(a.getGroupUUID());
}
return groupDetailFactory.create(groupId).call();
@@ -361,6 +362,7 @@ class GroupAdminServiceImpl extends BaseServiceImplementation implements
}
final Account.Id me = getAccountId();
final Set<AccountGroup.Id> groupsToEvict = new HashSet<AccountGroup.Id>();
for (final AccountGroupInclude.Key k : keys) {
final AccountGroupInclude m =
db.accountGroupIncludes().get(k);
@@ -385,9 +387,12 @@ class GroupAdminServiceImpl extends BaseServiceImplementation implements
Collections.singleton(audit));
}
db.accountGroupIncludes().delete(Collections.singleton(m));
groupIncludeCache.evictInclude(m.getIncludeId());
groupsToEvict.add(k.getIncludeId());
}
}
for (AccountGroup group : db.accountGroups().get(groupsToEvict)) {
groupIncludeCache.evictInclude(group.getGroupUUID());
}
return VoidResult.INSTANCE;
}
});

View File

@@ -42,10 +42,10 @@ class MyGroupsFactory extends Handler<List<AccountGroup>> {
@Override
public List<AccountGroup> call() throws Exception {
final Set<AccountGroup.Id> effective = user.getEffectiveGroups();
final Set<AccountGroup.UUID> effective = user.getEffectiveGroups();
final int cnt = effective.size();
final List<AccountGroup> groupList = new ArrayList<AccountGroup>(cnt);
for (final AccountGroup.Id groupId : effective) {
for (final AccountGroup.UUID groupId : effective) {
groupList.add(groupCache.get(groupId));
}
Collections.sort(groupList, new Comparator<AccountGroup>() {

View File

@@ -127,7 +127,7 @@ final class PatchSetPublishDetailFactory extends Handler<PatchSetPublishDetail>
}
private void computeAllowed() {
final Set<AccountGroup.Id> am = user.getEffectiveGroups();
final Set<AccountGroup.UUID> am = user.getEffectiveGroups();
final ProjectState pe = projectCache.get(change.getProject());
for (ApprovalCategory.Id category : approvalTypes.getApprovalCategories()) {
RefControl rc = pe.controlFor(user).controlForRef(change.getDest());
@@ -136,7 +136,7 @@ final class PatchSetPublishDetailFactory extends Handler<PatchSetPublishDetail>
}
}
private void computeAllowed(final Set<AccountGroup.Id> am,
private void computeAllowed(final Set<AccountGroup.UUID> am,
final List<RefRight> list, ApprovalCategory.Id category) {
Set<ApprovalCategoryValue.Id> s = allowed.get(category);
@@ -146,7 +146,7 @@ final class PatchSetPublishDetailFactory extends Handler<PatchSetPublishDetail>
}
for (final RefRight r : list) {
if (!am.contains(r.getAccountGroupId())) {
if (!am.contains(r.getAccountGroupUUID())) {
continue;
}
final ApprovalType at =

View File

@@ -116,6 +116,8 @@ public final class RefRight {
@Column(id = 3)
protected short maxValue;
protected transient AccountGroup.UUID groupUUID;
protected RefRight() {
}
@@ -123,11 +125,12 @@ public final class RefRight {
this.key = key;
}
public RefRight(final RefRight refRight, final AccountGroup.Id groupId) {
public RefRight(final RefRight refRight, final AccountGroup.UUID groupId) {
this(new RefRight.Key(refRight.getKey().projectName,
refRight.getKey().refPattern, refRight.getKey().categoryId, groupId));
refRight.getKey().refPattern, refRight.getKey().categoryId, null));
setMinValue(refRight.getMinValue());
setMaxValue(refRight.getMaxValue());
setAccountGroupUUID(groupId);
}
public RefRight.Key getKey() {
@@ -161,6 +164,14 @@ public final class RefRight {
return key.groupId;
}
public AccountGroup.UUID getAccountGroupUUID() {
return groupUUID;
}
public void setAccountGroupUUID(AccountGroup.UUID uuid) {
groupUUID = uuid;
}
public short getMinValue() {
return minValue;
}

View File

@@ -34,8 +34,8 @@ public class AnonymousUser extends CurrentUser {
}
@Override
public Set<AccountGroup.Id> getEffectiveGroups() {
return authConfig.getAnonymousGroups();
public Set<AccountGroup.UUID> getEffectiveGroups() {
return Collections.singleton(AccountGroup.ANONYMOUS_USERS);
}
@Override

View File

@@ -56,7 +56,7 @@ public abstract class CurrentUser {
*
* @return active groups for this user.
*/
public abstract Set<AccountGroup.Id> getEffectiveGroups();
public abstract Set<AccountGroup.UUID> getEffectiveGroups();
/** Set of changes starred by this user. */
public abstract Set<Change.Id> getStarredChanges();

View File

@@ -43,11 +43,14 @@ import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.SocketAddress;
import java.net.URL;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import java.util.Set;
@@ -139,6 +142,28 @@ public class IdentifiedUser extends CurrentUser {
private static final Logger log =
LoggerFactory.getLogger(IdentifiedUser.class);
private static final Set<AccountGroup.UUID> registeredGroups =
new AbstractSet<AccountGroup.UUID>() {
private final List<AccountGroup.UUID> groups =
Collections.unmodifiableList(Arrays.asList(new AccountGroup.UUID[] {
AccountGroup.ANONYMOUS_USERS, AccountGroup.REGISTERED_USERS}));
@Override
public boolean contains(Object o) {
return groups.contains(o);
}
@Override
public Iterator<AccountGroup.UUID> iterator() {
return groups.iterator();
}
@Override
public int size() {
return groups.size();
}
};
private final Provider<String> canonicalUrl;
private final Realm realm;
private final AccountCache accountCache;
@@ -154,7 +179,7 @@ public class IdentifiedUser extends CurrentUser {
private AccountState state;
private Set<String> emailAddresses;
private Set<AccountGroup.Id> effectiveGroups;
private Set<AccountGroup.UUID> effectiveGroups;
private Set<Change.Id> starredChanges;
private Collection<AccountProjectWatch> notificationFilters;
@@ -217,14 +242,14 @@ public class IdentifiedUser extends CurrentUser {
}
@Override
public Set<AccountGroup.Id> getEffectiveGroups() {
public Set<AccountGroup.UUID> getEffectiveGroups() {
if (effectiveGroups == null) {
Set<AccountGroup.Id> seedGroups;
Set<AccountGroup.UUID> seedGroups;
if (authConfig.isIdentityTrustable(state().getExternalIds())) {
seedGroups = realm.groups(state());
} else {
seedGroups = authConfig.getRegisteredGroups();
seedGroups = registeredGroups;
}
effectiveGroups = getIncludedGroups(seedGroups);
@@ -233,14 +258,14 @@ public class IdentifiedUser extends CurrentUser {
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);
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.Id id = groupQueue.remove();
AccountGroup.UUID id = groupQueue.remove();
for (final AccountGroup.Id groupId : groupIncludeCache.getByInclude(id)) {
for (final AccountGroup.UUID groupId : groupIncludeCache.getByInclude(id)) {
if (includes.add(groupId)) {
groupQueue.add(groupId);
}

View File

@@ -36,21 +36,21 @@ public class PeerDaemonUser extends CurrentUser {
PeerDaemonUser create(@Assisted SocketAddress peer);
}
private final Set<AccountGroup.Id> effectiveGroups;
private final Set<AccountGroup.UUID> effectiveGroups;
private final SocketAddress peer;
@Inject
protected PeerDaemonUser(AuthConfig authConfig, @Assisted SocketAddress peer) {
super(AccessPath.SSH_COMMAND, authConfig);
final HashSet<AccountGroup.Id> g = new HashSet<AccountGroup.Id>();
final HashSet<AccountGroup.UUID> g = new HashSet<AccountGroup.UUID>();
g.add(authConfig.getAdministratorsGroup());
this.effectiveGroups = Collections.unmodifiableSet(g);
this.peer = peer;
}
@Override
public Set<AccountGroup.Id> getEffectiveGroups() {
public Set<AccountGroup.UUID> getEffectiveGroups() {
return effectiveGroups;
}

View File

@@ -28,18 +28,18 @@ import java.util.Set;
public class ReplicationUser extends CurrentUser {
/** Magic set of groups enabling read of any project and reference. */
public static final Set<AccountGroup.Id> EVERYTHING_VISIBLE =
Collections.unmodifiableSet(new HashSet<AccountGroup.Id>(0));
public static final Set<AccountGroup.UUID> EVERYTHING_VISIBLE =
Collections.unmodifiableSet(new HashSet<AccountGroup.UUID>(0));
public interface Factory {
ReplicationUser create(@Assisted Set<AccountGroup.Id> authGroups);
ReplicationUser create(@Assisted Set<AccountGroup.UUID> authGroups);
}
private final Set<AccountGroup.Id> effectiveGroups;
private final Set<AccountGroup.UUID> effectiveGroups;
@Inject
protected ReplicationUser(AuthConfig authConfig,
@Assisted Set<AccountGroup.Id> authGroups) {
@Assisted Set<AccountGroup.UUID> authGroups) {
super(AccessPath.REPLICATION, authConfig);
if (authGroups == EVERYTHING_VISIBLE) {
@@ -53,12 +53,12 @@ public class ReplicationUser extends CurrentUser {
}
}
private static Set<AccountGroup.Id> copy(Set<AccountGroup.Id> groups) {
return Collections.unmodifiableSet(new HashSet<AccountGroup.Id>(groups));
private static Set<AccountGroup.UUID> copy(Set<AccountGroup.UUID> groups) {
return Collections.unmodifiableSet(new HashSet<AccountGroup.UUID>(groups));
}
@Override
public Set<AccountGroup.Id> getEffectiveGroups() {
public Set<AccountGroup.UUID> getEffectiveGroups() {
return effectiveGroups;
}

View File

@@ -22,7 +22,6 @@ import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.cache.Cache;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.EntryCreator;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.SchemaFactory;
import com.google.inject.Inject;
@@ -90,18 +89,13 @@ public class AccountCacheImpl implements AccountCache {
static class ByIdLoader extends EntryCreator<Account.Id, AccountState> {
private final SchemaFactory<ReviewDb> schema;
private final Set<AccountGroup.Id> registered;
private final Set<AccountGroup.Id> anonymous;
private final GroupCache groupCache;
private final Cache<String, Account.Id> byName;
@Inject
ByIdLoader(SchemaFactory<ReviewDb> sf, AuthConfig auth,
GroupCache groupCache,
ByIdLoader(SchemaFactory<ReviewDb> sf, GroupCache groupCache,
@Named(BYUSER_NAME) Cache<String, Account.Id> byUsername) {
this.schema = sf;
this.registered = auth.getRegisteredGroups();
this.anonymous = auth.getAnonymousGroups();
this.groupCache = groupCache;
this.byName = byUsername;
}
@@ -133,21 +127,18 @@ public class AccountCacheImpl implements AccountCache {
Collections.unmodifiableCollection(db.accountExternalIds().byAccount(
who).toList());
Set<AccountGroup.Id> internalGroups = new HashSet<AccountGroup.Id>();
Set<AccountGroup.UUID> internalGroups = new HashSet<AccountGroup.UUID>();
for (AccountGroupMember g : db.accountGroupMembers().byAccount(who)) {
final AccountGroup.Id groupId = g.getAccountGroupId();
final AccountGroup group = groupCache.get(groupId);
if (group != null && group.getType() == AccountGroup.Type.INTERNAL) {
internalGroups.add(groupId);
internalGroups.add(group.getGroupUUID());
}
}
if (internalGroups.isEmpty()) {
internalGroups = registered;
} else {
internalGroups.addAll(registered);
internalGroups = Collections.unmodifiableSet(internalGroups);
}
internalGroups.add(AccountGroup.REGISTERED_USERS);
internalGroups.add(AccountGroup.ANONYMOUS_USERS);
internalGroups = Collections.unmodifiableSet(internalGroups);
return new AccountState(account, internalGroups, externalIds);
}
@@ -156,6 +147,8 @@ public class AccountCacheImpl implements AccountCache {
public AccountState missing(final Account.Id accountId) {
final Account account = new Account(accountId);
final Collection<AccountExternalId> ids = Collections.emptySet();
final Set<AccountGroup.UUID> anonymous =
Collections.singleton(AccountGroup.ANONYMOUS_USERS);
return new AccountState(account, anonymous, ids);
}
}

View File

@@ -275,7 +275,9 @@ public class AccountManager {
// is going to be the site's administrator and just make them that
// to bootstrap the authentication database.
//
final AccountGroup.Id admin = authConfig.getAdministratorsGroup();
final AccountGroup.UUID uuid = authConfig.getAdministratorsGroup();
final AccountGroup g = db.accountGroups().byUUID(uuid).iterator().next();
final AccountGroup.Id admin = g.getId();
final AccountGroupMember m =
new AccountGroupMember(new AccountGroupMember.Key(newId, admin));
db.accountGroupMembersAudit().insert(

View File

@@ -26,11 +26,11 @@ import java.util.Set;
public class AccountState {
private final Account account;
private final Set<AccountGroup.Id> internalGroups;
private final Set<AccountGroup.UUID> internalGroups;
private final Collection<AccountExternalId> externalIds;
public AccountState(final Account account,
final Set<AccountGroup.Id> actualGroups,
final Set<AccountGroup.UUID> actualGroups,
final Collection<AccountExternalId> externalIds) {
this.account = account;
this.internalGroups = actualGroups;
@@ -89,7 +89,7 @@ public class AccountState {
}
/** The set of groups maintained directly within the Gerrit database. */
public Set<AccountGroup.Id> getInternalGroups() {
public Set<AccountGroup.UUID> getInternalGroups() {
return internalGroups;
}

View File

@@ -51,7 +51,7 @@ public final class DefaultRealm implements Realm {
}
@Override
public Set<AccountGroup.Id> groups(final AccountState who) {
public Set<AccountGroup.UUID> groups(final AccountState who) {
return who.getInternalGroups();
}

View File

@@ -20,7 +20,6 @@ import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.cache.Cache;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.EntryCreator;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gwtorm.client.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Module;
@@ -113,12 +112,10 @@ public class GroupCacheImpl implements GroupCache {
static class ByIdLoader extends EntryCreator<AccountGroup.Id, AccountGroup> {
private final SchemaFactory<ReviewDb> schema;
private final AccountGroup.Id administrators;
@Inject
ByIdLoader(final SchemaFactory<ReviewDb> sf, final AuthConfig authConfig) {
ByIdLoader(final SchemaFactory<ReviewDb> sf) {
schema = sf;
administrators = authConfig.getAdministratorsGroup();
}
@Override
@@ -142,7 +139,6 @@ public class GroupCacheImpl implements GroupCache {
new AccountGroup.NameKey("Deleted Group" + key.toString());
final AccountGroup g = new AccountGroup(name, key, null);
g.setType(AccountGroup.Type.SYSTEM);
g.setOwnerGroupId(administrators);
return g;
}
}

View File

@@ -20,8 +20,8 @@ import java.util.Collection;
/** Tracks group inclusions in memory for efficient access. */
public interface GroupIncludeCache {
public Collection<AccountGroup.Id> getByInclude(AccountGroup.Id groupId);
public Collection<AccountGroup.UUID> getByInclude(AccountGroup.UUID groupId);
public void evictInclude(AccountGroup.Id groupId);
public void evictInclude(AccountGroup.UUID groupId);
}

View File

@@ -21,16 +21,17 @@ import com.google.gerrit.server.cache.Cache;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.EntryCreator;
import com.google.gwtorm.client.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** Tracks group inclusions in memory for efficient access. */
@Singleton
@@ -41,8 +42,8 @@ public class GroupIncludeCacheImpl implements GroupIncludeCache {
return new CacheModule() {
@Override
protected void configure() {
final TypeLiteral<Cache<AccountGroup.Id, Collection<AccountGroup.Id>>> byInclude =
new TypeLiteral<Cache<AccountGroup.Id, Collection<AccountGroup.Id>>>() {};
final TypeLiteral<Cache<AccountGroup.UUID, Collection<AccountGroup.UUID>>> byInclude =
new TypeLiteral<Cache<AccountGroup.UUID, Collection<AccountGroup.UUID>>>() {};
core(byInclude, BYINCLUDE_NAME).populateWith(ByIncludeLoader.class);
bind(GroupIncludeCacheImpl.class);
@@ -51,23 +52,24 @@ public class GroupIncludeCacheImpl implements GroupIncludeCache {
};
}
private final Cache<AccountGroup.Id, Collection<AccountGroup.Id>> byInclude;
private final Cache<AccountGroup.UUID, Collection<AccountGroup.UUID>> byInclude;
@Inject
GroupIncludeCacheImpl(
@Named(BYINCLUDE_NAME) Cache<AccountGroup.Id, Collection<AccountGroup.Id>> byInclude) {
@Named(BYINCLUDE_NAME) Cache<AccountGroup.UUID, Collection<AccountGroup.UUID>> byInclude) {
this.byInclude = byInclude;
}
public Collection<AccountGroup.Id> getByInclude(final AccountGroup.Id groupId) {
public Collection<AccountGroup.UUID> getByInclude(AccountGroup.UUID groupId) {
return byInclude.get(groupId);
}
public void evictInclude(AccountGroup.Id groupId) {
public void evictInclude(AccountGroup.UUID groupId) {
byInclude.remove(groupId);
}
static class ByIncludeLoader extends EntryCreator<AccountGroup.Id, Collection<AccountGroup.Id>> {
static class ByIncludeLoader extends
EntryCreator<AccountGroup.UUID, Collection<AccountGroup.UUID>> {
private final SchemaFactory<ReviewDb> schema;
@Inject
@@ -76,14 +78,23 @@ public class GroupIncludeCacheImpl implements GroupIncludeCache {
}
@Override
public Collection<AccountGroup.Id> createEntry(final AccountGroup.Id key) throws Exception {
public Collection<AccountGroup.UUID> createEntry(final AccountGroup.UUID key) throws Exception {
final ReviewDb db = schema.open();
try {
ArrayList<AccountGroup.Id> groupArray = new ArrayList<AccountGroup.Id> ();
for (AccountGroupInclude agi : db.accountGroupIncludes().byInclude(key)) {
groupArray.add(agi.getGroupId());
List<AccountGroup> group = db.accountGroups().byUUID(key).toList();
if (group.size() != 1) {
return Collections.emptyList();
}
Set<AccountGroup.Id> ids = new HashSet<AccountGroup.Id>();
for (AccountGroupInclude agi : db.accountGroupIncludes().byInclude(group.get(0).getId())) {
ids.add(agi.getGroupId());
}
Set<AccountGroup.UUID> groupArray = new HashSet<AccountGroup.UUID> ();
for (AccountGroup g : db.accountGroups().get(ids)) {
groupArray.add(g.getGroupUUID());
}
return Collections.unmodifiableCollection(groupArray);
} finally {
db.close();
@@ -91,7 +102,7 @@ public class GroupIncludeCacheImpl implements GroupIncludeCache {
}
@Override
public Collection<AccountGroup.Id> missing(final AccountGroup.Id key) {
public Collection<AccountGroup.UUID> missing(final AccountGroup.UUID key) {
return Collections.emptyList();
}
}

View File

@@ -34,6 +34,7 @@ import org.eclipse.jgit.lib.PersonIdent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
public class PerformCreateGroup {
@@ -160,8 +161,9 @@ public class PerformCreateGroup {
db.accountGroupIncludes().insert(includeList);
db.accountGroupIncludesAudit().insert(includesAudit);
for (AccountGroup.Id includeId : groups) {
groupIncludeCache.evictInclude(includeId);
for (AccountGroup group : db.accountGroups().get(
new HashSet<AccountGroup.Id>(groups))) {
groupIncludeCache.evictInclude(group.getGroupUUID());
}
}
}

View File

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

View File

@@ -133,7 +133,7 @@ import javax.net.ssl.SSLSocketFactory;
}
}
Set<AccountGroup.Id> queryForGroups(final DirContext ctx,
Set<AccountGroup.UUID> queryForGroups(final DirContext ctx,
final String username, LdapQuery.Result account)
throws NamingException, AccountException {
final LdapSchema schema = getSchema(ctx);
@@ -175,12 +175,12 @@ import javax.net.ssl.SSLSocketFactory;
}
}
final Set<AccountGroup.Id> actual = new HashSet<AccountGroup.Id>();
final Set<AccountGroup.UUID> actual = new HashSet<AccountGroup.UUID>();
for (String dn : groupDNs) {
for (AccountGroup group : groupCache
.get(new AccountGroup.ExternalNameKey(dn))) {
if (group.getType() == AccountGroup.Type.LDAP) {
actual.add(group.getId());
actual.add(group.getGroupUUID());
}
}
}

View File

@@ -32,8 +32,8 @@ public class LdapModule extends CacheModule {
@Override
protected void configure() {
final TypeLiteral<Cache<String, Set<AccountGroup.Id>>> groups =
new TypeLiteral<Cache<String, Set<AccountGroup.Id>>>() {};
final TypeLiteral<Cache<String, Set<AccountGroup.UUID>>> groups =
new TypeLiteral<Cache<String, Set<AccountGroup.UUID>>>() {};
core(groups, GROUP_CACHE).maxAge(1, HOURS) //
.populateWith(LdapRealm.MemberLoader.class);

View File

@@ -68,14 +68,14 @@ class LdapRealm implements Realm {
private final Cache<String, Account.Id> usernameCache;
private final Set<Account.FieldName> readOnlyAccountFields;
private final Cache<String, Set<AccountGroup.Id>> membershipCache;
private final Cache<String, Set<AccountGroup.UUID>> membershipCache;
@Inject
LdapRealm(
final Helper helper,
final AuthConfig authConfig,
final EmailExpander emailExpander,
@Named(LdapModule.GROUP_CACHE) final Cache<String, Set<AccountGroup.Id>> membershipCache,
@Named(LdapModule.GROUP_CACHE) final Cache<String, Set<AccountGroup.UUID>> membershipCache,
@Named(LdapModule.USERNAME_CACHE) final Cache<String, Account.Id> usernameCache,
@GerritServerConfig final Config config) {
this.helper = helper;
@@ -241,8 +241,8 @@ class LdapRealm implements Realm {
}
@Override
public Set<AccountGroup.Id> groups(final AccountState who) {
final HashSet<AccountGroup.Id> r = new HashSet<AccountGroup.Id>();
public Set<AccountGroup.UUID> groups(final AccountState who) {
final HashSet<AccountGroup.UUID> r = new HashSet<AccountGroup.UUID>();
r.addAll(membershipCache.get(findId(who.getExternalIds())));
r.addAll(who.getInternalGroups());
return r;
@@ -324,7 +324,7 @@ class LdapRealm implements Realm {
}
}
static class MemberLoader extends EntryCreator<String, Set<AccountGroup.Id>> {
static class MemberLoader extends EntryCreator<String, Set<AccountGroup.UUID>> {
private final Helper helper;
@Inject
@@ -333,7 +333,7 @@ class LdapRealm implements Realm {
}
@Override
public Set<AccountGroup.Id> createEntry(final String username)
public Set<AccountGroup.UUID> createEntry(final String username)
throws Exception {
final DirContext ctx = helper.open();
try {
@@ -348,7 +348,7 @@ class LdapRealm implements Realm {
}
@Override
public Set<AccountGroup.Id> missing(final String key) {
public Set<AccountGroup.UUID> missing(final String key) {
return Collections.emptySet();
}
}

View File

@@ -29,9 +29,7 @@ import org.eclipse.jgit.lib.Config;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** Authentication related settings from {@code gerrit.config}. */
@Singleton
@@ -45,10 +43,8 @@ public class AuthConfig {
private final boolean cookieSecure;
private final SignedToken emailReg;
private final AccountGroup.Id administratorGroup;
private final Set<AccountGroup.Id> anonymousGroups;
private final Set<AccountGroup.Id> registeredGroups;
private final AccountGroup.Id batchUsersGroup;
private final AccountGroup.UUID administratorGroup;
private final AccountGroup.UUID batchUsersGroup;
private final boolean allowGoogleAccountUpgrade;
@@ -64,13 +60,8 @@ public class AuthConfig {
cookieSecure = cfg.getBoolean("auth", "cookiesecure", false);
emailReg = new SignedToken(5 * 24 * 60 * 60, s.registerEmailPrivateKey);
final HashSet<AccountGroup.Id> r = new HashSet<AccountGroup.Id>(2);
r.add(s.anonymousGroupId);
r.add(s.registeredGroupId);
registeredGroups = Collections.unmodifiableSet(r);
anonymousGroups = Collections.singleton(s.anonymousGroupId);
administratorGroup = s.adminGroupId;
batchUsersGroup = s.batchUsersGroupId;
administratorGroup = s.adminGroupUUID;
batchUsersGroup = s.batchUsersGroupUUID;
if (authType == AuthType.OPENID) {
allowGoogleAccountUpgrade =
@@ -127,25 +118,15 @@ public class AuthConfig {
}
/** Identity of the magic group with full powers. */
public AccountGroup.Id getAdministratorsGroup() {
public AccountGroup.UUID getAdministratorsGroup() {
return administratorGroup;
}
/** Identity of the group whose service is degraded to lower priority. */
public AccountGroup.Id getBatchUsersGroup() {
public AccountGroup.UUID getBatchUsersGroup() {
return batchUsersGroup;
}
/** Groups that all users, including anonymous users, belong to. */
public Set<AccountGroup.Id> getAnonymousGroups() {
return anonymousGroups;
}
/** Groups that all users who have created an account belong to. */
public Set<AccountGroup.Id> getRegisteredGroups() {
return registeredGroups;
}
/** OpenID identities which the server permits for authentication. */
public List<OpenIdProviderPattern> getAllowedOpenIDs() {
return allowedOpenIDs;

View File

@@ -310,10 +310,10 @@ public class ConfigUtil {
* @return the actual groups resolved from the database. If no groups are
* found, returns an empty {@code Set}, never {@code null}.
*/
public static Set<AccountGroup.Id> groupsFor(
public static Set<AccountGroup.UUID> groupsFor(
SchemaFactory<ReviewDb> dbfactory, String[] groupNames, Logger log,
String groupNotFoundWarning) {
final Set<AccountGroup.Id> result = new HashSet<AccountGroup.Id>();
final Set<AccountGroup.UUID> result = new HashSet<AccountGroup.UUID>();
try {
final ReviewDb db = dbfactory.open();
try {
@@ -322,9 +322,16 @@ public class ConfigUtil {
db.accountGroupNames().get(new AccountGroup.NameKey(name));
if (group == null) {
log.warn(MessageFormat.format(groupNotFoundWarning, name));
} else {
result.add(group.getId());
continue;
}
AccountGroup ag = db.accountGroups().get(group.getId());
if (ag == null) {
log.warn(MessageFormat.format(groupNotFoundWarning, name));
continue;
}
result.add(ag.getGroupUUID());
}
} finally {
db.close();
@@ -345,7 +352,7 @@ public class ConfigUtil {
* @return the actual groups resolved from the database. If no groups are
* found, returns an empty {@code Set}, never {@code null}.
*/
public static Set<AccountGroup.Id> groupsFor(
public static Set<AccountGroup.UUID> groupsFor(
SchemaFactory<ReviewDb> dbfactory, String[] groupNames, Logger log) {
return groupsFor(dbfactory, groupNames, log,
"Group \"{0}\" not in database, skipping.");

View File

@@ -22,21 +22,17 @@ import com.google.inject.Inject;
import org.eclipse.jgit.lib.Config;
import java.util.Collections;
import java.util.HashSet;
public class GitReceivePackGroupsProvider extends GroupSetProvider {
@Inject
public GitReceivePackGroupsProvider(@GerritServerConfig Config config,
AuthConfig authConfig, SchemaFactory<ReviewDb> db) {
SchemaFactory<ReviewDb> db) {
super(config, db, "receive", null, "allowGroup");
// If no group was set, default to "registered users"
//
if (groupIds.isEmpty()) {
HashSet<AccountGroup.Id> all = new HashSet<AccountGroup.Id>();
all.addAll(authConfig.getRegisteredGroups());
all.removeAll(authConfig.getAnonymousGroups());
groupIds = Collections.unmodifiableSet(all);
groupIds = Collections.singleton(AccountGroup.REGISTERED_USERS);
}
}
}

View File

@@ -27,15 +27,15 @@ import java.util.HashSet;
public class GitUploadPackGroupsProvider extends GroupSetProvider {
@Inject
public GitUploadPackGroupsProvider(@GerritServerConfig Config config,
AuthConfig authConfig, SchemaFactory<ReviewDb> db) {
SchemaFactory<ReviewDb> db) {
super(config, db, "upload", null, "allowGroup");
// If no group was set, default to "registered users" and "anonymous"
//
if (groupIds.isEmpty()) {
HashSet<AccountGroup.Id> all = new HashSet<AccountGroup.Id>();
all.addAll(authConfig.getRegisteredGroups());
all.addAll(authConfig.getAnonymousGroups());
HashSet<AccountGroup.UUID> all = new HashSet<AccountGroup.UUID>();
all.add(AccountGroup.REGISTERED_USERS);
all.add(AccountGroup.ANONYMOUS_USERS);
groupIds = Collections.unmodifiableSet(all);
}
}

View File

@@ -30,11 +30,11 @@ import org.slf4j.LoggerFactory;
import java.util.Set;
public abstract class GroupSetProvider implements
Provider<Set<AccountGroup.Id>> {
Provider<Set<AccountGroup.UUID>> {
private static final Logger log =
LoggerFactory.getLogger(GroupSetProvider.class);
protected Set<AccountGroup.Id> groupIds;
protected Set<AccountGroup.UUID> groupIds;
@Inject
protected GroupSetProvider(@GerritServerConfig Config config,
@@ -44,7 +44,7 @@ public abstract class GroupSetProvider implements
}
@Override
public Set<AccountGroup.Id> get() {
public Set<AccountGroup.UUID> get() {
return groupIds;
}
}

View File

@@ -15,7 +15,6 @@
package com.google.gerrit.server.config;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.reviewdb.SystemConfig;
import com.google.gwtorm.client.SchemaFactory;
import com.google.inject.Inject;
@@ -37,11 +36,11 @@ import java.util.Collections;
public class ProjectCreatorGroupsProvider extends GroupSetProvider {
@Inject
public ProjectCreatorGroupsProvider(@GerritServerConfig final Config config,
final SystemConfig systemConfig, final SchemaFactory<ReviewDb> db) {
final AuthConfig authConfig, final SchemaFactory<ReviewDb> db) {
super(config, db, "repository", "*", "createGroup");
if (groupIds.isEmpty()) {
groupIds = Collections.singleton(systemConfig.adminGroupId);
groupIds = Collections.singleton(authConfig.getAdministratorsGroup());
}
}
}

View File

@@ -37,7 +37,7 @@ import java.util.Set;
public class ProjectOwnerGroupsProvider extends GroupSetProvider {
@Inject
public ProjectOwnerGroupsProvider(
@ProjectCreatorGroups final Set<AccountGroup.Id> creatorGroups,
@ProjectCreatorGroups final Set<AccountGroup.UUID> creatorGroups,
@GerritServerConfig final Config config, final SchemaFactory<ReviewDb> db) {
super(config, db, "repository", "*", "ownerGroup");

View File

@@ -354,7 +354,7 @@ public class PushReplication implements ReplicationQueue {
String[] authGroupNames =
cfg.getStringList("remote", rc.getName(), "authGroup");
final Set<AccountGroup.Id> authGroups;
final Set<AccountGroup.UUID> authGroups;
if (authGroupNames.length > 0) {
authGroups = ConfigUtil.groupsFor(db, authGroupNames, //
log, "Group \"{0}\" not in database, removing from authGroup");

View File

@@ -40,6 +40,7 @@ import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.TrackingFooters;
import com.google.gerrit.server.mail.CreateChangeSender;
@@ -145,6 +146,7 @@ public class ReceiveCommits implements PreReceiveHook, PostReceiveHook {
private final ChangeHookRunner hooks;
private final GitRepositoryManager repoManager;
private final ProjectCache projectCache;
private final GroupCache groupCache;
private final String canonicalWebUrl;
private final PersonIdent gerritIdent;
private final TrackingFooters trackingFooters;
@@ -181,6 +183,7 @@ public class ReceiveCommits implements PreReceiveHook, PostReceiveHook {
final ChangeHookRunner hooks,
final ProjectCache projectCache,
final GitRepositoryManager repoManager,
final GroupCache groupCache,
@CanonicalWebUrl @Nullable final String canonicalWebUrl,
@GerritPersonIdent final PersonIdent gerritIdent,
final TrackingFooters trackingFooters,
@@ -199,6 +202,7 @@ public class ReceiveCommits implements PreReceiveHook, PostReceiveHook {
this.hooks = hooks;
this.projectCache = projectCache;
this.repoManager = repoManager;
this.groupCache = groupCache;
this.canonicalWebUrl = canonicalWebUrl;
this.gerritIdent = gerritIdent;
this.trackingFooters = trackingFooters;
@@ -417,9 +421,14 @@ public class ReceiveCommits implements PreReceiveHook, PostReceiveHook {
AbstractAgreement bestAgreement = null;
ContributorAgreement bestCla = null;
OUTER: for (AccountGroup.Id groupId : currentUser.getEffectiveGroups()) {
OUTER: for (AccountGroup.UUID groupUUID : currentUser.getEffectiveGroups()) {
AccountGroup group = groupCache.get(groupUUID);
if (group == null) {
continue;
}
final List<AccountGroupAgreement> temp =
db.accountGroupAgreements().byGroup(groupId).toList();
db.accountGroupAgreements().byGroup(group.getId()).toList();
Collections.reverse(temp);

View File

@@ -69,8 +69,8 @@ public abstract class ChangeEmail extends OutgoingEmail {
/** Is the from user in an email squelching group? */
final IdentifiedUser user = args.identifiedUserFactory.create(id);
final Set<AccountGroup.Id> gids = user.getEffectiveGroups();
for (final AccountGroup.Id gid : gids) {
final Set<AccountGroup.UUID> gids = user.getEffectiveGroups();
for (final AccountGroup.UUID gid : gids) {
if (args.groupCache.get(gid).isEmailOnlyAuthors()) {
emailOnlyAuthors = true;
break;
@@ -273,11 +273,11 @@ public abstract class ChangeEmail extends OutgoingEmail {
}
/** Get the groups which own the project. */
protected Set<AccountGroup.Id> getProjectOwners() {
protected Set<AccountGroup.UUID> getProjectOwners() {
final ProjectState r;
r = args.projectCache.get(change.getProject());
return r != null ? r.getOwners() : Collections.<AccountGroup.Id> emptySet();
return r != null ? r.getOwners() : Collections.<AccountGroup.UUID> emptySet();
}
/** TO or CC all vested parties (change owner, patch set uploader, author). */

View File

@@ -20,6 +20,7 @@ import com.google.gerrit.reviewdb.AccountGroupMember;
import com.google.gerrit.reviewdb.AccountProjectWatch;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.AccountProjectWatch.NotifyType;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.ssh.SshInfo;
import com.google.gwtorm.client.OrmException;
import com.google.inject.Inject;
@@ -34,10 +35,13 @@ public class CreateChangeSender extends NewChangeSender {
public CreateChangeSender create(Change change);
}
private final GroupCache groupCache;
@Inject
public CreateChangeSender(EmailArguments ea, SshInfo sshInfo,
@Assisted Change c) {
GroupCache groupCache, @Assisted Change c) {
super(ea, sshInfo, c);
this.groupCache = groupCache;
}
@Override
@@ -52,10 +56,13 @@ public class CreateChangeSender extends NewChangeSender {
// Try to mark interested owners with a TO and not a BCC line.
//
final Set<Account.Id> owners = new HashSet<Account.Id>();
for (AccountGroup.Id g : getProjectOwners()) {
for (AccountGroupMember m : args.db.get().accountGroupMembers()
.byGroup(g)) {
owners.add(m.getAccountId());
for (AccountGroup.UUID uuid : getProjectOwners()) {
AccountGroup group = groupCache.get(uuid);
if (group != null) {
for (AccountGroupMember m : args.db.get().accountGroupMembers()
.byGroup(group.getId())) {
owners.add(m.getAccountId());
}
}
}

View File

@@ -33,19 +33,19 @@ import java.util.Set;
public class AccessControlModule extends FactoryModule {
@Override
protected void configure() {
bind(new TypeLiteral<Set<AccountGroup.Id>>() {}) //
bind(new TypeLiteral<Set<AccountGroup.UUID>>() {}) //
.annotatedWith(ProjectCreatorGroups.class) //
.toProvider(ProjectCreatorGroupsProvider.class).in(SINGLETON);
bind(new TypeLiteral<Set<AccountGroup.Id>>() {}) //
bind(new TypeLiteral<Set<AccountGroup.UUID>>() {}) //
.annotatedWith(ProjectOwnerGroups.class) //
.toProvider(ProjectOwnerGroupsProvider.class).in(SINGLETON);
bind(new TypeLiteral<Set<AccountGroup.Id>>() {}) //
bind(new TypeLiteral<Set<AccountGroup.UUID>>() {}) //
.annotatedWith(GitUploadPackGroups.class) //
.toProvider(GitUploadPackGroupsProvider.class).in(SINGLETON);
bind(new TypeLiteral<Set<AccountGroup.Id>>() {}) //
bind(new TypeLiteral<Set<AccountGroup.UUID>>() {}) //
.annotatedWith(GitReceivePackGroups.class) //
.toProvider(GitReceivePackGroupsProvider.class).in(SINGLETON);

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.server.project;
import com.google.gerrit.reviewdb.AccountGroup;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.RefRight;
import com.google.gerrit.reviewdb.ReviewDb;
@@ -34,8 +35,11 @@ import org.eclipse.jgit.lib.Repository;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.locks.Lock;
@@ -191,9 +195,27 @@ public class ProjectCacheImpl implements ProjectCache {
cfg.load(git);
final Project p = cfg.getProject();
final Collection<RefRight> rights =
Collections.unmodifiableCollection(db.refRights().byProject(key)
.toList());
Collection<RefRight> rights = db.refRights().byProject(key).toList();
Set<AccountGroup.Id> groupIds = new HashSet<AccountGroup.Id>();
for (RefRight r : rights) {
groupIds.add(r.getAccountGroupId());
}
Map<AccountGroup.Id, AccountGroup> groupsById =
db.accountGroups().toMap(db.accountGroups().get(groupIds));
for (RefRight r : rights) {
AccountGroup group = groupsById.get(r.getAccountGroupId());
if (group != null) {
r.setAccountGroupUUID(group.getGroupUUID());
} else {
r.setAccountGroupUUID(new AccountGroup.UUID("DELETED_GROUP_"
+ r.getAccountGroupId().get()));
}
}
rights = Collections.unmodifiableCollection(rights);
return projectStateFactory.create(p, rights);
} finally {
git.close();

View File

@@ -101,16 +101,16 @@ public class ProjectControl {
ProjectControl create(CurrentUser who, ProjectState ps);
}
private final Set<AccountGroup.Id> uploadGroups;
private final Set<AccountGroup.Id> receiveGroups;
private final Set<AccountGroup.UUID> uploadGroups;
private final Set<AccountGroup.UUID> receiveGroups;
private final RefControl.Factory refControlFactory;
private final CurrentUser user;
private final ProjectState state;
@Inject
ProjectControl(@GitUploadPackGroups Set<AccountGroup.Id> uploadGroups,
@GitReceivePackGroups Set<AccountGroup.Id> receiveGroups,
ProjectControl(@GitUploadPackGroups Set<AccountGroup.UUID> uploadGroups,
@GitReceivePackGroups Set<AccountGroup.UUID> receiveGroups,
final RefControl.Factory refControlFactory,
@Assisted CurrentUser who, @Assisted ProjectState ps) {
this.uploadGroups = uploadGroups;
@@ -197,10 +197,10 @@ public class ProjectControl {
// TODO (anatol.pomazau): Try to merge this method with similar RefRightsForPattern#canPerform
private boolean canPerformOnAnyRef(ApprovalCategory.Id actionId,
short requireValue) {
final Set<AccountGroup.Id> groups = user.getEffectiveGroups();
final Set<AccountGroup.UUID> groups = user.getEffectiveGroups();
for (final RefRight pr : state.getAllRights(actionId, true)) {
if (groups.contains(pr.getAccountGroupId())
if (groups.contains(pr.getAccountGroupUUID())
&& pr.getMaxValue() >= requireValue) {
return true;
}

View File

@@ -46,7 +46,7 @@ public class ProjectState {
private final Project project;
private final Collection<RefRight> localRights;
private final Set<AccountGroup.Id> localOwners;
private final Set<AccountGroup.UUID> localOwners;
private volatile Collection<RefRight> inheritedRights;
@@ -75,12 +75,12 @@ public class ProjectState {
this.project = project;
this.localRights = rights;
final HashSet<AccountGroup.Id> groups = new HashSet<AccountGroup.Id>();
final HashSet<AccountGroup.UUID> groups = new HashSet<AccountGroup.UUID>();
for (final RefRight right : rights) {
if (ApprovalCategory.OWN.equals(right.getApprovalCategoryId())
&& right.getMaxValue() > 0
&& right.getRefPattern().equals(RefRight.ALL)) {
groups.add(right.getAccountGroupId());
groups.add(right.getAccountGroupUUID());
}
}
localOwners = Collections.unmodifiableSet(groups);
@@ -216,7 +216,7 @@ public class ProjectState {
* are no local owners the local owners of the nearest parent project
* that has local owners are returned
*/
public Set<AccountGroup.Id> getOwners() {
public Set<AccountGroup.UUID> getOwners() {
if (!localOwners.isEmpty() || isSpecialWildProject()
|| project.getParent() == null) {
return localOwners;
@@ -237,11 +237,11 @@ public class ProjectState {
* owners) and all groups to which the owner privilege for 'refs/*' is
* assigned for one of the parent projects (the inherited owners).
*/
public Set<AccountGroup.Id> getAllOwners() {
final HashSet<AccountGroup.Id> owners = new HashSet<AccountGroup.Id>();
public Set<AccountGroup.UUID> getAllOwners() {
final HashSet<AccountGroup.UUID> owners = new HashSet<AccountGroup.UUID>();
for (final RefRight right : getAllRights(ApprovalCategory.OWN, true)) {
if (right.getMaxValue() > 0 && right.getRefPattern().equals(RefRight.ALL)) {
owners.add(right.getAccountGroupId());
owners.add(right.getAccountGroupUUID());
}
}
return Collections.unmodifiableSet(owners);

View File

@@ -68,7 +68,6 @@ public class RefControl {
RefControl create(ProjectControl projectControl, String ref);
}
private final SystemConfig systemConfig;
private final ProjectControl projectControl;
private final String refName;
@@ -76,10 +75,8 @@ public class RefControl {
private Boolean canForgeCommitter;
@Inject
protected RefControl(final SystemConfig systemConfig,
@Assisted final ProjectControl projectControl,
protected RefControl(@Assisted final ProjectControl projectControl,
@Assisted String ref) {
this.systemConfig = systemConfig;
if (isRE(ref)) {
ref = shortestExample(ref);
@@ -270,7 +267,7 @@ public class RefControl {
public short normalize(ApprovalCategory.Id category, short score) {
short minAllowed = 0, maxAllowed = 0;
for (RefRight r : getApplicableRights(category)) {
if (getCurrentUser().getEffectiveGroups().contains(r.getAccountGroupId())) {
if (getCurrentUser().getEffectiveGroups().contains(r.getAccountGroupUUID())) {
minAllowed = (short) Math.min(minAllowed, r.getMinValue());
maxAllowed = (short) Math.max(maxAllowed, r.getMaxValue());
}
@@ -320,9 +317,9 @@ public class RefControl {
* @param groups The groups of the user
* @return The allowed value for this ref for all the specified groups
*/
private boolean allowedValueForRef(Set<AccountGroup.Id> groups, short level) {
private boolean allowedValueForRef(Set<AccountGroup.UUID> groups, short level) {
for (RefRight right : rights) {
if (groups.contains(right.getAccountGroupId())
if (groups.contains(right.getAccountGroupUUID())
&& right.getMaxValue() >= level) {
return true;
}
@@ -332,7 +329,7 @@ public class RefControl {
}
boolean canPerform(ApprovalCategory.Id actionId, short level) {
final Set<AccountGroup.Id> groups = getCurrentUser().getEffectiveGroups();
final Set<AccountGroup.UUID> groups = getCurrentUser().getEffectiveGroups();
List<RefRight> allRights = new ArrayList<RefRight>();
allRights.addAll(getAllRights(actionId));
@@ -538,9 +535,9 @@ public class RefControl {
*/
private Set<RefRight> resolveOwnerGroups(final RefRight refRight) {
final Set<RefRight> resolvedRefRights = new HashSet<RefRight>();
if (refRight.getAccountGroupId().equals(systemConfig.ownerGroupId)) {
for (final AccountGroup.Id ownerGroup : getProjectState().getAllOwners()) {
if (!ownerGroup.equals(systemConfig.ownerGroupId)) {
if (AccountGroup.PROJECT_OWNERS.equals(refRight.getAccountGroupUUID())) {
for (final AccountGroup.UUID ownerGroup : getProjectState().getAllOwners()) {
if (!AccountGroup.PROJECT_OWNERS.equals(ownerGroup)) {
resolvedRefRights.add(new RefRight(refRight, ownerGroup));
}
}

View File

@@ -344,15 +344,15 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
//
AccountGroup g = args.groupCache.get(new AccountGroup.NameKey(who));
if (g != null) {
return visibleto(new SingleGroupUser(args.authConfig, g.getId()));
return visibleto(new SingleGroupUser(args.authConfig, g.getGroupUUID()));
}
Collection<AccountGroup> matches =
args.groupCache.get(new AccountGroup.ExternalNameKey(who));
if (matches != null && !matches.isEmpty()) {
HashSet<AccountGroup.Id> ids = new HashSet<AccountGroup.Id>();
HashSet<AccountGroup.UUID> ids = new HashSet<AccountGroup.UUID>();
for (AccountGroup group : matches) {
ids.add(group.getId());
ids.add(group.getGroupUUID());
}
return visibleto(new SingleGroupUser(args.authConfig, ids));
}

View File

@@ -26,19 +26,19 @@ import java.util.Collections;
import java.util.Set;
final class SingleGroupUser extends CurrentUser {
private final Set<AccountGroup.Id> groups;
private final Set<AccountGroup.UUID> groups;
SingleGroupUser(AuthConfig authConfig, AccountGroup.Id groupId) {
SingleGroupUser(AuthConfig authConfig, AccountGroup.UUID groupId) {
this(authConfig, Collections.singleton(groupId));
}
SingleGroupUser(AuthConfig authConfig, Set<AccountGroup.Id> groups) {
SingleGroupUser(AuthConfig authConfig, Set<AccountGroup.UUID> groups) {
super(AccessPath.UNKNOWN, authConfig);
this.groups = groups;
}
@Override
public Set<AccountGroup.Id> getEffectiveGroups() {
public Set<AccountGroup.UUID> getEffectiveGroups() {
return groups;
}

View File

@@ -94,7 +94,7 @@ public abstract class CategoryFunction {
final FunctionState state) {
RefControl rc = state.controlFor(user);
for (final RefRight pr : rc.getApplicableRights(at.getCategory().getId())) {
if (user.getEffectiveGroups().contains(pr.getAccountGroupId())
if (user.getEffectiveGroups().contains(pr.getAccountGroupUUID())
&& (pr.getMinValue() < 0 || pr.getMaxValue() > 0)) {
return true;
}

View File

@@ -147,7 +147,7 @@ public class FunctionState {
//
short minAllowed = 0, maxAllowed = 0;
for (final RefRight r : rc.getApplicableRights(a.getCategoryId())) {
final AccountGroup.Id grp = r.getAccountGroupId();
final AccountGroup.UUID grp = r.getAccountGroupUUID();
if (user.getEffectiveGroups().contains(grp)) {
minAllowed = (short) Math.min(minAllowed, r.getMinValue());
maxAllowed = (short) Math.max(maxAllowed, r.getMaxValue());

View File

@@ -45,7 +45,7 @@ public class SubmitFunction extends CategoryFunction {
if (valid(at, state)) {
RefControl rc = state.controlFor(user);
for (final RefRight pr : rc.getApplicableRights(at.getCategory().getId())) {
if (user.getEffectiveGroups().contains(pr.getAccountGroupId())
if (user.getEffectiveGroups().contains(pr.getAccountGroupUUID())
&& pr.getMaxValue() > 0) {
return true;
}

View File

@@ -278,7 +278,7 @@ public class FromAddressGeneratorProviderTest extends TestCase {
account.setFullName(name);
account.setPreferredEmail(email);
final AccountState s =
new AccountState(account, Collections.<AccountGroup.Id> emptySet(),
new AccountState(account, Collections.<AccountGroup.UUID> emptySet(),
Collections.<AccountExternalId> emptySet());
return s;
}

View File

@@ -45,8 +45,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class RefControlTest extends TestCase {
@@ -188,25 +190,24 @@ public class RefControlTest extends TestCase {
private final Project.NameKey local = new Project.NameKey("test");
private final Project.NameKey parent = new Project.NameKey("parent");
private final AccountGroup.Id admin = new AccountGroup.Id(1);
private final AccountGroup.Id anonymous = new AccountGroup.Id(2);
private final AccountGroup.Id registered = new AccountGroup.Id(3);
private final AccountGroup.Id owners = new AccountGroup.Id(4);
private final AccountGroup.UUID admin = new AccountGroup.UUID("test.admin");
private final AccountGroup.UUID anonymous = AccountGroup.ANONYMOUS_USERS;
private final AccountGroup.UUID registered = AccountGroup.REGISTERED_USERS;
private final AccountGroup.Id devs = new AccountGroup.Id(5);
private final AccountGroup.Id fixers = new AccountGroup.Id(6);
private final AccountGroup.UUID devs = new AccountGroup.UUID("test.devs");
private final AccountGroup.UUID fixers = new AccountGroup.UUID("test.fixers");
private final SystemConfig systemConfig;
private final AuthConfig authConfig;
private final AnonymousUser anonymousUser;
private final Map<AccountGroup.UUID, AccountGroup.Id> groupIds =
new HashMap<AccountGroup.UUID, AccountGroup.Id>();
public RefControlTest() {
systemConfig = SystemConfig.create();
systemConfig.adminGroupId = admin;
systemConfig.anonymousGroupId = anonymous;
systemConfig.registeredGroupId = registered;
systemConfig.ownerGroupId = owners;
systemConfig.batchUsersGroupId = anonymous;
systemConfig.adminGroupUUID = admin;
systemConfig.batchUsersGroupUUID = anonymous;
try {
byte[] bin = "abcdefghijklmnopqrstuvwxyz".getBytes("UTF-8");
systemConfig.registerEmailPrivateKey = Base64.encodeBase64String(bin);
@@ -249,15 +250,22 @@ public class RefControlTest extends TestCase {
}
private void grant(Project.NameKey project, ApprovalCategory.Id categoryId,
AccountGroup.Id group, String ref, int maxValue) {
AccountGroup.UUID group, String ref, int maxValue) {
grant(project, categoryId, group, ref, maxValue, maxValue);
}
private void grant(Project.NameKey project, ApprovalCategory.Id categoryId, AccountGroup.Id group,
String ref, int minValue, int maxValue) {
private void grant(Project.NameKey project, ApprovalCategory.Id categoryId,
AccountGroup.UUID groupUUID, String ref, int minValue, int maxValue) {
AccountGroup.Id groupId = groupIds.get(groupUUID);
if (groupId == null) {
groupId = new AccountGroup.Id(groupIds.size() + 1);
groupIds.put(groupUUID, groupId);
}
RefRight right =
new RefRight(new RefRight.Key(project, new RefPattern(ref),
categoryId, group));
categoryId, groupId));
right.setAccountGroupUUID(groupUUID);
right.setMinValue((short) minValue);
right.setMaxValue((short) maxValue);
@@ -270,15 +278,15 @@ public class RefControlTest extends TestCase {
}
}
private ProjectControl user(AccountGroup.Id... memberOf) {
private ProjectControl user(AccountGroup.UUID... memberOf) {
RefControl.Factory refControlFactory = new RefControl.Factory() {
@Override
public RefControl create(final ProjectControl projectControl, final String ref) {
return new RefControl(systemConfig, projectControl, ref);
return new RefControl(projectControl, ref);
}
};
return new ProjectControl(Collections.<AccountGroup.Id> emptySet(),
Collections.<AccountGroup.Id> emptySet(), refControlFactory,
return new ProjectControl(Collections.<AccountGroup.UUID> emptySet(),
Collections.<AccountGroup.UUID> emptySet(), refControlFactory,
new MockUser(memberOf), newProjectState());
}
@@ -295,17 +303,17 @@ public class RefControlTest extends TestCase {
}
private class MockUser extends CurrentUser {
private final Set<AccountGroup.Id> groups;
private final Set<AccountGroup.UUID> groups;
MockUser(AccountGroup.Id[] groupId) {
MockUser(AccountGroup.UUID[] groupId) {
super(AccessPath.UNKNOWN, RefControlTest.this.authConfig);
groups = new HashSet<AccountGroup.Id>(Arrays.asList(groupId));
groups = new HashSet<AccountGroup.UUID>(Arrays.asList(groupId));
groups.add(registered);
groups.add(anonymous);
}
@Override
public Set<AccountGroup.Id> getEffectiveGroups() {
public Set<AccountGroup.UUID> getEffectiveGroups() {
return groups;
}

View File

@@ -32,6 +32,7 @@ import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.ssh.SshInfo;
import com.google.gerrit.sshd.args4j.AccountGroupIdHandler;
import com.google.gerrit.sshd.args4j.AccountGroupUUIDHandler;
import com.google.gerrit.sshd.args4j.AccountIdHandler;
import com.google.gerrit.sshd.args4j.PatchSetIdHandler;
import com.google.gerrit.sshd.args4j.ProjectControlHandler;
@@ -117,6 +118,7 @@ public class SshModule extends FactoryModule {
registerOptionHandler(Account.Id.class, AccountIdHandler.class);
registerOptionHandler(AccountGroup.Id.class, AccountGroupIdHandler.class);
registerOptionHandler(AccountGroup.UUID.class, AccountGroupUUIDHandler.class);
registerOptionHandler(PatchSet.Id.class, PatchSetIdHandler.class);
registerOptionHandler(ProjectControl.class, ProjectControlHandler.class);
registerOptionHandler(SocketAddress.class, SocketAddressHandler.class);

View File

@@ -0,0 +1,57 @@
// Copyright (C) 2009 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.sshd.args4j;
import com.google.gerrit.reviewdb.AccountGroup;
import com.google.gerrit.server.account.GroupCache;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.OptionDef;
import org.kohsuke.args4j.spi.OptionHandler;
import org.kohsuke.args4j.spi.Parameters;
import org.kohsuke.args4j.spi.Setter;
public class AccountGroupUUIDHandler extends OptionHandler<AccountGroup.UUID> {
private final GroupCache groupCache;
@SuppressWarnings("unchecked")
@Inject
public AccountGroupUUIDHandler(final GroupCache groupCache,
@Assisted final CmdLineParser parser, @Assisted final OptionDef option,
@Assisted final Setter setter) {
super(parser, option, setter);
this.groupCache = groupCache;
}
@Override
public final int parseArguments(final Parameters params)
throws CmdLineException {
final String n = params.getParameter(0);
final AccountGroup group = groupCache.get(new AccountGroup.NameKey(n));
if (group == null) {
throw new CmdLineException(owner, "Group \"" + n + "\" does not exist");
}
setter.addValue(group.getGroupUUID());
return 1;
}
@Override
public final String getDefaultMetaVariable() {
return "GROUP";
}
}

View File

@@ -23,6 +23,7 @@ import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.reviewdb.Project.SubmitType;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.config.ProjectCreatorGroups;
import com.google.gerrit.server.config.ProjectOwnerGroups;
import com.google.gerrit.server.git.GitRepositoryManager;
@@ -64,7 +65,7 @@ final class CreateProject extends BaseCommand {
private String projectName;
@Option(name = "--owner", aliases = {"-o"}, usage = "owner(s) of project")
private List<AccountGroup.Id> ownerIds;
private List<AccountGroup.UUID> ownerIds;
@Option(name = "--parent", aliases = {"-p"}, metaVar = "NAME", usage = "parent project")
private ProjectControl newParent;
@@ -104,13 +105,16 @@ final class CreateProject extends BaseCommand {
@Inject
private ProjectCache projectCache;
@Inject
private GroupCache groupCache;
@Inject
@ProjectCreatorGroups
private Set<AccountGroup.Id> projectCreatorGroups;
private Set<AccountGroup.UUID> projectCreatorGroups;
@Inject
@ProjectOwnerGroups
private Set<AccountGroup.Id> projectOwnerGroups;
private Set<AccountGroup.UUID> projectOwnerGroups;
@Inject
private IdentifiedUser currentUser;
@@ -202,10 +206,12 @@ final class CreateProject extends BaseCommand {
ConfigInvalidException {
List<RefRight> access = new ArrayList<RefRight>();
for (AccountGroup.Id ownerId : ownerIds) {
for (AccountGroup.UUID ownerId : ownerIds) {
AccountGroup group = groupCache.get(ownerId);
final RefRight.Key prk =
new RefRight.Key(nameKey, new RefRight.RefPattern(
RefRight.ALL), ApprovalCategory.OWN, ownerId);
RefRight.ALL), ApprovalCategory.OWN, group.getId());
final RefRight pr = new RefRight(prk);
pr.setMaxValue((short) 1);
pr.setMinValue((short) 1);
@@ -251,9 +257,9 @@ final class CreateProject extends BaseCommand {
if (ownerIds != null && !ownerIds.isEmpty()) {
ownerIds =
new ArrayList<AccountGroup.Id>(new HashSet<AccountGroup.Id>(ownerIds));
new ArrayList<AccountGroup.UUID>(new HashSet<AccountGroup.UUID>(ownerIds));
} else {
ownerIds = new ArrayList<AccountGroup.Id>(projectOwnerGroups);
ownerIds = new ArrayList<AccountGroup.UUID>(projectOwnerGroups);
}
while (branch.startsWith("/")) {