Replace use of AccountGroup by an interface for various classes

Previously, GroupDescription.Internal served only as a marker for
internal groups and simply delegated to AccountGroup. By converting
GroupDescription.Internal to a real interface, we gain a lot of
flexibility. For instance, we are free to use another class to
represent internal groups (which will be necessary for the migration
of groups to NoteDb).

Change-Id: If7397898d8508184a2ccdc7c371ed60ada7d6f3e
This commit is contained in:
Alice Kober-Sotzek
2017-08-16 17:41:38 +02:00
parent 6da54a4009
commit 3a68432798
28 changed files with 154 additions and 146 deletions

View File

@@ -25,19 +25,15 @@ import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.Sandboxed; import com.google.gerrit.acceptance.Sandboxed;
import com.google.gerrit.acceptance.TestAccount; import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.common.data.GlobalCapability; import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupDescriptions;
import com.google.gerrit.extensions.api.changes.ReviewInput; import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.common.ChangeInput; import com.google.gerrit.extensions.common.ChangeInput;
import com.google.gerrit.extensions.common.GroupInfo; import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.common.SuggestedReviewerInfo; import com.google.gerrit.extensions.common.SuggestedReviewerInfo;
import com.google.gerrit.extensions.restapi.RestApiException; import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.TopLevelResource; import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.group.CreateGroup; import com.google.gerrit.server.group.CreateGroup;
import com.google.gerrit.server.group.GroupsCollection;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -48,8 +44,6 @@ import org.junit.Test;
public class SuggestReviewersIT extends AbstractDaemonTest { public class SuggestReviewersIT extends AbstractDaemonTest {
@Inject private CreateGroup.Factory createGroupFactory; @Inject private CreateGroup.Factory createGroupFactory;
@Inject private GroupsCollection groups;
private AccountGroup group1; private AccountGroup group1;
private AccountGroup group2; private AccountGroup group2;
private AccountGroup group3; private AccountGroup group3;
@@ -432,8 +426,7 @@ public class SuggestReviewersIT extends AbstractDaemonTest {
private AccountGroup group(String name) throws Exception { private AccountGroup group(String name) throws Exception {
GroupInfo group = createGroupFactory.create(name(name)).apply(TopLevelResource.INSTANCE, null); GroupInfo group = createGroupFactory.create(name(name)).apply(TopLevelResource.INSTANCE, null);
GroupDescription.Basic d = groups.parseInternal(Url.decode(group.id)); return groupCache.get(new AccountGroup.UUID(group.id));
return GroupDescriptions.toAccountGroup(d);
} }
private TestAccount user(String name, String fullName, String emailName, AccountGroup... groups) private TestAccount user(String name, String fullName, String emailName, AccountGroup... groups)

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.common.data;
import com.google.gerrit.common.Nullable; import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.AccountGroup;
import java.sql.Timestamp;
/** Group methods exposed by the GroupBackend. */ /** Group methods exposed by the GroupBackend. */
public class GroupDescription { public class GroupDescription {
@@ -42,10 +43,18 @@ public class GroupDescription {
String getUrl(); String getUrl();
} }
/** The extended information exposed by internal groups backed by an AccountGroup. */ /** The extended information exposed by internal groups. */
public interface Internal extends Basic { public interface Internal extends Basic {
/** @return the backing AccountGroup. */
AccountGroup getAccountGroup(); AccountGroup.Id getId();
String getDescription();
AccountGroup.UUID getOwnerGroupUUID();
boolean isVisibleToAll();
Timestamp getCreatedOn();
} }
private GroupDescription() {} private GroupDescription() {}

View File

@@ -17,18 +17,11 @@ package com.google.gerrit.common.data;
import com.google.gerrit.common.Nullable; import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.PageLinks; import com.google.gerrit.common.PageLinks;
import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.AccountGroup;
import java.sql.Timestamp;
/** Utility class for building GroupDescription objects. */ /** Utility class for building GroupDescription objects. */
public class GroupDescriptions { public class GroupDescriptions {
@Nullable
public static AccountGroup toAccountGroup(GroupDescription.Basic group) {
if (group instanceof GroupDescription.Internal) {
return ((GroupDescription.Internal) group).getAccountGroup();
}
return null;
}
public static GroupDescription.Internal forAccountGroup(AccountGroup group) { public static GroupDescription.Internal forAccountGroup(AccountGroup group) {
return new GroupDescription.Internal() { return new GroupDescription.Internal() {
@Override @Override
@@ -41,11 +34,6 @@ public class GroupDescriptions {
return group.getName(); return group.getName();
} }
@Override
public AccountGroup getAccountGroup() {
return group;
}
@Override @Override
@Nullable @Nullable
public String getEmailAddress() { public String getEmailAddress() {
@@ -53,10 +41,34 @@ public class GroupDescriptions {
} }
@Override @Override
@Nullable
public String getUrl() { public String getUrl() {
return "#" + PageLinks.toGroup(getGroupUUID()); return "#" + PageLinks.toGroup(getGroupUUID());
} }
@Override
public AccountGroup.Id getId() {
return group.getId();
}
@Override
public String getDescription() {
return group.getDescription();
}
@Override
public AccountGroup.UUID getOwnerGroupUUID() {
return group.getOwnerGroupUUID();
}
@Override
public boolean isVisibleToAll() {
return group.isVisibleToAll();
}
@Override
public Timestamp getCreatedOn() {
return group.getCreatedOn();
}
}; };
} }

View File

@@ -46,8 +46,7 @@ public class GroupInfo {
url = a.getUrl(); url = a.getUrl();
if (a instanceof GroupDescription.Internal) { if (a instanceof GroupDescription.Internal) {
AccountGroup group = ((GroupDescription.Internal) a).getAccountGroup(); description = ((GroupDescription.Internal) a).getDescription();
description = group.getDescription();
} }
} }

View File

@@ -18,7 +18,7 @@ import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_MAI
import com.google.gerrit.common.Nullable; import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.GlobalCapability; import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.GroupDescriptions; import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.errors.InvalidSshKeyException; import com.google.gerrit.common.errors.InvalidSshKeyException;
import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.extensions.annotations.RequiresCapability;
@@ -211,8 +211,8 @@ public class CreateAccount implements RestModifyView<TopLevelResource, AccountIn
Set<AccountGroup.UUID> groupUuids = new HashSet<>(); Set<AccountGroup.UUID> groupUuids = new HashSet<>();
if (groups != null) { if (groups != null) {
for (String g : groups) { for (String g : groups) {
AccountGroup group = GroupDescriptions.toAccountGroup(groupsCollection.parseInternal(g)); GroupDescription.Internal internalGroup = groupsCollection.parseInternal(g);
groupUuids.add(group.getGroupUUID()); groupUuids.add(internalGroup.getGroupUUID());
} }
} }
return groupUuids; return groupUuids;

View File

@@ -142,12 +142,15 @@ public class GroupControl {
} }
public boolean isOwner() { public boolean isOwner() {
AccountGroup accountGroup = GroupDescriptions.toAccountGroup(group); if (isOwner != null) {
if (accountGroup == null) { return isOwner;
isOwner = false; }
} else if (isOwner == null) {
AccountGroup.UUID ownerUUID = accountGroup.getOwnerGroupUUID(); if (group instanceof GroupDescription.Internal) {
AccountGroup.UUID ownerUUID = ((GroupDescription.Internal) group).getOwnerGroupUUID();
isOwner = getUser().getEffectiveGroups().contains(ownerUUID) || canAdministrateServer(); isOwner = getUser().getEffectiveGroups().contains(ownerUUID) || canAdministrateServer();
} else {
isOwner = false;
} }
return isOwner; return isOwner;
} }
@@ -189,7 +192,9 @@ public class GroupControl {
} }
private boolean canSeeMembers() { private boolean canSeeMembers() {
AccountGroup accountGroup = GroupDescriptions.toAccountGroup(group); if (group instanceof GroupDescription.Internal) {
return (accountGroup != null && accountGroup.isVisibleToAll()) || isOwner(); return ((GroupDescription.Internal) group).isVisibleToAll() || isOwner();
}
return false;
} }
} }

View File

@@ -85,6 +85,6 @@ public class InternalGroupBackend implements GroupBackend {
@Override @Override
public boolean isVisibleToAll(AccountGroup.UUID uuid) { public boolean isVisibleToAll(AccountGroup.UUID uuid) {
GroupDescription.Internal g = get(uuid); GroupDescription.Internal g = get(uuid);
return g != null && g.getAccountGroup().isVisibleToAll(); return g != null && g.isVisibleToAll();
} }
} }

View File

@@ -87,10 +87,8 @@ public class AddIncludedGroups implements RestModifyView<GroupResource, Input> {
public List<GroupInfo> apply(GroupResource resource, Input input) public List<GroupInfo> apply(GroupResource resource, Input input)
throws MethodNotAllowedException, AuthException, UnprocessableEntityException, OrmException, throws MethodNotAllowedException, AuthException, UnprocessableEntityException, OrmException,
ResourceNotFoundException { ResourceNotFoundException {
AccountGroup group = resource.toAccountGroup(); GroupDescription.Internal group =
if (group == null) { resource.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
throw new MethodNotAllowedException();
}
input = Input.init(input); input = Input.init(input);
GroupControl control = resource.getControl(); GroupControl control = resource.getControl();

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.server.group;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.client.AuthType; import com.google.gerrit.extensions.client.AuthType;
import com.google.gerrit.extensions.common.AccountInfo; import com.google.gerrit.extensions.common.AccountInfo;
@@ -111,10 +112,8 @@ public class AddMembers implements RestModifyView<GroupResource, Input> {
public List<AccountInfo> apply(GroupResource resource, Input input) public List<AccountInfo> apply(GroupResource resource, Input input)
throws AuthException, MethodNotAllowedException, UnprocessableEntityException, OrmException, throws AuthException, MethodNotAllowedException, UnprocessableEntityException, OrmException,
IOException, ConfigInvalidException, ResourceNotFoundException { IOException, ConfigInvalidException, ResourceNotFoundException {
AccountGroup internalGroup = resource.toAccountGroup(); GroupDescription.Internal internalGroup =
if (internalGroup == null) { resource.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
throw new MethodNotAllowedException();
}
input = Input.init(input); input = Input.init(input);
GroupControl control = resource.getControl(); GroupControl control = resource.getControl();

View File

@@ -166,8 +166,8 @@ public class CreateGroup implements RestModifyView<TopLevelResource, GroupInput>
private AccountGroup.Id owner(GroupInput input) throws UnprocessableEntityException { private AccountGroup.Id owner(GroupInput input) throws UnprocessableEntityException {
if (input.ownerId != null) { if (input.ownerId != null) {
GroupDescription.Basic d = groups.parseInternal(Url.decode(input.ownerId)); GroupDescription.Internal d = groups.parseInternal(Url.decode(input.ownerId));
return GroupDescriptions.toAccountGroup(d).getId(); return d.getId();
} }
return null; return null;
} }

View File

@@ -54,10 +54,8 @@ public class DeleteIncludedGroups implements RestModifyView<GroupResource, Input
public Response<?> apply(GroupResource resource, Input input) public Response<?> apply(GroupResource resource, Input input)
throws AuthException, MethodNotAllowedException, UnprocessableEntityException, OrmException, throws AuthException, MethodNotAllowedException, UnprocessableEntityException, OrmException,
ResourceNotFoundException { ResourceNotFoundException {
AccountGroup internalGroup = resource.toAccountGroup(); GroupDescription.Internal internalGroup =
if (internalGroup == null) { resource.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
throw new MethodNotAllowedException();
}
input = Input.init(input); input = Input.init(input);
final GroupControl control = resource.getControl(); final GroupControl control = resource.getControl();

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.server.group; package com.google.gerrit.server.group;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException; import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
@@ -56,10 +57,8 @@ public class DeleteMembers implements RestModifyView<GroupResource, Input> {
public Response<?> apply(GroupResource resource, Input input) public Response<?> apply(GroupResource resource, Input input)
throws AuthException, MethodNotAllowedException, UnprocessableEntityException, OrmException, throws AuthException, MethodNotAllowedException, UnprocessableEntityException, OrmException,
IOException, ConfigInvalidException, ResourceNotFoundException { IOException, ConfigInvalidException, ResourceNotFoundException {
AccountGroup internalGroup = resource.toAccountGroup(); GroupDescription.Internal internalGroup =
if (internalGroup == null) { resource.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
throw new MethodNotAllowedException();
}
input = Input.init(input); input = Input.init(input);
final GroupControl control = resource.getControl(); final GroupControl control = resource.getControl();

View File

@@ -64,10 +64,9 @@ public class GetAuditLog implements RestReadView<GroupResource> {
@Override @Override
public List<? extends GroupAuditEventInfo> apply(GroupResource rsrc) public List<? extends GroupAuditEventInfo> apply(GroupResource rsrc)
throws AuthException, MethodNotAllowedException, OrmException { throws AuthException, MethodNotAllowedException, OrmException {
AccountGroup group = rsrc.toAccountGroup(); GroupDescription.Internal group =
if (group == null) { rsrc.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
throw new MethodNotAllowedException(); if (!rsrc.getControl().isOwner()) {
} else if (!rsrc.getControl().isOwner()) {
throw new AuthException("Not group owner"); throw new AuthException("Not group owner");
} }

View File

@@ -15,19 +15,17 @@
package com.google.gerrit.server.group; package com.google.gerrit.server.group;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException; import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.RestReadView; import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.inject.Singleton; import com.google.inject.Singleton;
@Singleton @Singleton
public class GetDescription implements RestReadView<GroupResource> { public class GetDescription implements RestReadView<GroupResource> {
@Override @Override
public String apply(GroupResource resource) throws MethodNotAllowedException { public String apply(GroupResource resource) throws MethodNotAllowedException {
AccountGroup group = resource.toAccountGroup(); GroupDescription.Internal group =
if (group == null) { resource.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
throw new MethodNotAllowedException();
}
return Strings.nullToEmpty(group.getDescription()); return Strings.nullToEmpty(group.getDescription());
} }
} }

View File

@@ -14,12 +14,12 @@
package com.google.gerrit.server.group; package com.google.gerrit.server.group;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.common.GroupInfo; import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException; import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestReadView; import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.account.GroupControl; import com.google.gerrit.server.account.GroupControl;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
@@ -40,10 +40,8 @@ public class GetOwner implements RestReadView<GroupResource> {
@Override @Override
public GroupInfo apply(GroupResource resource) public GroupInfo apply(GroupResource resource)
throws MethodNotAllowedException, ResourceNotFoundException, OrmException { throws MethodNotAllowedException, ResourceNotFoundException, OrmException {
AccountGroup group = resource.toAccountGroup(); GroupDescription.Internal group =
if (group == null) { resource.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
throw new MethodNotAllowedException();
}
try { try {
GroupControl c = controlFactory.validateFor(group.getOwnerGroupUUID()); GroupControl c = controlFactory.validateFor(group.getOwnerGroupUUID());
return json.format(c.getGroup()); return json.format(c.getGroup());

View File

@@ -19,7 +19,6 @@ import static com.google.gerrit.extensions.client.ListGroupsOption.MEMBERS;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.gerrit.common.data.GroupDescription; import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupDescriptions;
import com.google.gerrit.extensions.client.ListGroupsOption; import com.google.gerrit.extensions.client.ListGroupsOption;
import com.google.gerrit.extensions.common.GroupInfo; import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.common.GroupOptionsInfo; import com.google.gerrit.extensions.common.GroupOptionsInfo;
@@ -37,8 +36,7 @@ import java.util.EnumSet;
public class GroupJson { public class GroupJson {
public static GroupOptionsInfo createOptions(GroupDescription.Basic group) { public static GroupOptionsInfo createOptions(GroupDescription.Basic group) {
GroupOptionsInfo options = new GroupOptionsInfo(); GroupOptionsInfo options = new GroupOptionsInfo();
AccountGroup ag = GroupDescriptions.toAccountGroup(group); if (isInternalGroup(group) && ((GroupDescription.Internal) group).isVisibleToAll()) {
if (ag != null && ag.isVisibleToAll()) {
options.visibleToAll = true; options.visibleToAll = true;
} }
return options; return options;
@@ -96,25 +94,30 @@ public class GroupJson {
info.url = Strings.emptyToNull(group.getUrl()); info.url = Strings.emptyToNull(group.getUrl());
info.options = createOptions(group); info.options = createOptions(group);
AccountGroup g = GroupDescriptions.toAccountGroup(group); if (isInternalGroup(group)) {
if (g != null) { GroupDescription.Internal internalGroup = (GroupDescription.Internal) group;
info.description = Strings.emptyToNull(g.getDescription()); info.description = Strings.emptyToNull(internalGroup.getDescription());
info.groupId = g.getId().get(); info.groupId = internalGroup.getId().get();
if (g.getOwnerGroupUUID() != null) { AccountGroup.UUID ownerGroupUUID = internalGroup.getOwnerGroupUUID();
info.ownerId = Url.encode(g.getOwnerGroupUUID().get()); if (ownerGroupUUID != null) {
GroupDescription.Basic o = groupBackend.get(g.getOwnerGroupUUID()); info.ownerId = Url.encode(ownerGroupUUID.get());
GroupDescription.Basic o = groupBackend.get(ownerGroupUUID);
if (o != null) { if (o != null) {
info.owner = o.getName(); info.owner = o.getName();
} }
} }
info.createdOn = g.getCreatedOn(); info.createdOn = internalGroup.getCreatedOn();
} }
return info; return info;
} }
private static boolean isInternalGroup(GroupDescription.Basic group) {
return group instanceof GroupDescription.Internal;
}
private GroupInfo initMembersAndIncludes(GroupResource rsrc, GroupInfo info) throws OrmException { private GroupInfo initMembersAndIncludes(GroupResource rsrc, GroupInfo info) throws OrmException {
if (rsrc.toAccountGroup() == null) { if (!rsrc.isInternalGroup()) {
return info; return info;
} }
try { try {

View File

@@ -15,12 +15,11 @@
package com.google.gerrit.server.group; package com.google.gerrit.server.group;
import com.google.gerrit.common.data.GroupDescription; import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupDescriptions;
import com.google.gerrit.extensions.restapi.RestResource; import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestView; import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.account.GroupControl; import com.google.gerrit.server.account.GroupControl;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import java.util.Optional;
public class GroupResource implements RestResource { public class GroupResource implements RestResource {
public static final TypeLiteral<RestView<GroupResource>> GROUP_KIND = public static final TypeLiteral<RestView<GroupResource>> GROUP_KIND =
@@ -44,12 +43,17 @@ public class GroupResource implements RestResource {
return getGroup().getName(); return getGroup().getName();
} }
public AccountGroup.UUID getGroupUUID() { public boolean isInternalGroup() {
return getGroup().getGroupUUID(); GroupDescription.Basic group = getGroup();
return group instanceof GroupDescription.Internal;
} }
public AccountGroup toAccountGroup() { public Optional<GroupDescription.Internal> asInternalGroup() {
return GroupDescriptions.toAccountGroup(getGroup()); GroupDescription.Basic group = getGroup();
if (group instanceof GroupDescription.Internal) {
return Optional.of((GroupDescription.Internal) group);
}
return Optional.empty();
} }
public GroupControl getControl() { public GroupControl getControl() {

View File

@@ -16,7 +16,6 @@ package com.google.gerrit.server.group;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import com.google.gerrit.common.data.GroupDescription; import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupDescriptions;
import com.google.gerrit.common.data.GroupReference; import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.registration.DynamicMap; import com.google.gerrit.extensions.registration.DynamicMap;
@@ -142,12 +141,13 @@ public class GroupsCollection
* @throws UnprocessableEntityException thrown if the group ID cannot be resolved, if the group is * @throws UnprocessableEntityException thrown if the group ID cannot be resolved, if the group is
* not visible to the calling user or if it's an external group * not visible to the calling user or if it's an external group
*/ */
public GroupDescription.Basic parseInternal(String id) throws UnprocessableEntityException { public GroupDescription.Internal parseInternal(String id) throws UnprocessableEntityException {
GroupDescription.Basic group = parse(id); GroupDescription.Basic group = parse(id);
if (GroupDescriptions.toAccountGroup(group) == null) { if (group instanceof GroupDescription.Internal) {
throw new UnprocessableEntityException(String.format("External Group Not Allowed: %s", id)); return (GroupDescription.Internal) group;
} }
return group;
throw new UnprocessableEntityException(String.format("External Group Not Allowed: %s", id));
} }
/** /**

View File

@@ -25,7 +25,6 @@ import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestView; import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.restapi.TopLevelResource; import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.group.AddIncludedGroups.PutIncludedGroup; import com.google.gerrit.server.group.AddIncludedGroups.PutIncludedGroup;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
@@ -67,10 +66,8 @@ public class IncludedGroupsCollection
@Override @Override
public IncludedGroupResource parse(GroupResource resource, IdString id) public IncludedGroupResource parse(GroupResource resource, IdString id)
throws MethodNotAllowedException, AuthException, ResourceNotFoundException, OrmException { throws MethodNotAllowedException, AuthException, ResourceNotFoundException, OrmException {
AccountGroup parent = resource.toAccountGroup(); GroupDescription.Internal parent =
if (parent == null) { resource.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
throw new MethodNotAllowedException();
}
GroupDescription.Basic member = GroupDescription.Basic member =
groupsCollection.parse(TopLevelResource.INSTANCE, id).getGroup(); groupsCollection.parse(TopLevelResource.INSTANCE, id).getGroup();
@@ -80,7 +77,7 @@ public class IncludedGroupsCollection
throw new ResourceNotFoundException(id); throw new ResourceNotFoundException(id);
} }
private boolean isMember(AccountGroup parent, GroupDescription.Basic member) private boolean isMember(GroupDescription.Internal parent, GroupDescription.Basic member)
throws OrmException, ResourceNotFoundException { throws OrmException, ResourceNotFoundException {
try { try {
return groups.isIncluded(dbProvider.get(), parent.getGroupUUID(), member.getGroupUUID()); return groups.isIncluded(dbProvider.get(), parent.getGroupUUID(), member.getGroupUUID());

View File

@@ -14,7 +14,6 @@
package com.google.gerrit.server.group; package com.google.gerrit.server.group;
import com.google.gerrit.common.data.GroupDescriptions;
import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.Response; import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestModifyView; import com.google.gerrit.extensions.restapi.RestModifyView;
@@ -44,14 +43,15 @@ public class Index implements RestModifyView<GroupResource, Input> {
throw new AuthException("not allowed to index group"); throw new AuthException("not allowed to index group");
} }
AccountGroup group = GroupDescriptions.toAccountGroup(rsrc.getGroup()); AccountGroup.UUID groupUuid = rsrc.getGroup().getGroupUUID();
if (group == null) { if (!rsrc.isInternalGroup()) {
throw new UnprocessableEntityException( throw new UnprocessableEntityException(
String.format("External Group Not Allowed: %s", rsrc.getGroupUUID().get())); String.format("External Group Not Allowed: %s", groupUuid.get()));
} }
AccountGroup accountGroup = groupCache.get(groupUuid);
// evicting the group from the cache, reindexes the group // evicting the group from the cache, reindexes the group
groupCache.evict(group); groupCache.evict(accountGroup);
return Response.none(); return Response.none();
} }
} }

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.server.group;
import static com.google.common.base.Strings.nullToEmpty; import static com.google.common.base.Strings.nullToEmpty;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.common.GroupInfo; import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException; import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
@@ -51,14 +52,13 @@ public class ListIncludedGroups implements RestReadView<GroupResource> {
@Override @Override
public List<GroupInfo> apply(GroupResource rsrc) throws MethodNotAllowedException, OrmException { public List<GroupInfo> apply(GroupResource rsrc) throws MethodNotAllowedException, OrmException {
if (rsrc.toAccountGroup() == null) { GroupDescription.Internal group =
throw new MethodNotAllowedException(); rsrc.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
}
boolean ownerOfParent = rsrc.getControl().isOwner(); boolean ownerOfParent = rsrc.getControl().isOwner();
List<GroupInfo> included = new ArrayList<>(); List<GroupInfo> included = new ArrayList<>();
Collection<AccountGroup.UUID> includedGroupUuids = Collection<AccountGroup.UUID> includedGroupUuids =
groupIncludeCache.subgroupsOf(rsrc.toAccountGroup().getGroupUUID()); groupIncludeCache.subgroupsOf(group.getGroupUUID());
for (AccountGroup.UUID includedGroupUuid : includedGroupUuids) { for (AccountGroup.UUID includedGroupUuid : includedGroupUuids) {
try { try {
GroupControl i = controlFactory.controlFor(includedGroupUuid); GroupControl i = controlFactory.controlFor(includedGroupUuid);
@@ -69,7 +69,7 @@ public class ListIncludedGroups implements RestReadView<GroupResource> {
log.warn( log.warn(
String.format( String.format(
"Group %s no longer available, included into %s", "Group %s no longer available, included into %s",
includedGroupUuid, rsrc.getGroup().getName())); includedGroupUuid, group.getName()));
continue; continue;
} }
} }

View File

@@ -15,6 +15,7 @@
package com.google.gerrit.server.group; package com.google.gerrit.server.group;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupDetail; import com.google.gerrit.common.data.GroupDetail;
import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.common.AccountInfo; import com.google.gerrit.extensions.common.AccountInfo;
@@ -61,11 +62,9 @@ public class ListMembers implements RestReadView<GroupResource> {
@Override @Override
public List<AccountInfo> apply(GroupResource resource) public List<AccountInfo> apply(GroupResource resource)
throws MethodNotAllowedException, OrmException { throws MethodNotAllowedException, OrmException {
if (resource.toAccountGroup() == null) { GroupDescription.Internal group =
throw new MethodNotAllowedException(); resource.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
} return apply(group.getGroupUUID());
return apply(resource.getGroupUUID());
} }
public List<AccountInfo> apply(AccountGroup group) throws OrmException { public List<AccountInfo> apply(AccountGroup group) throws OrmException {

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.server.group; package com.google.gerrit.server.group;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.registration.DynamicMap; import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.AcceptsCreate; import com.google.gerrit.extensions.restapi.AcceptsCreate;
@@ -71,10 +72,8 @@ public class MembersCollection
public MemberResource parse(GroupResource parent, IdString id) public MemberResource parse(GroupResource parent, IdString id)
throws MethodNotAllowedException, AuthException, ResourceNotFoundException, OrmException, throws MethodNotAllowedException, AuthException, ResourceNotFoundException, OrmException,
IOException, ConfigInvalidException { IOException, ConfigInvalidException {
AccountGroup group = parent.toAccountGroup(); GroupDescription.Internal group =
if (group == null) { parent.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
throw new MethodNotAllowedException();
}
IdentifiedUser user = accounts.parse(TopLevelResource.INSTANCE, id).getUser(); IdentifiedUser user = accounts.parse(TopLevelResource.INSTANCE, id).getUser();
if (parent.getControl().canSeeMember(user.getAccountId()) && isMember(group, user)) { if (parent.getControl().canSeeMember(user.getAccountId()) && isMember(group, user)) {
@@ -83,7 +82,7 @@ public class MembersCollection
throw new ResourceNotFoundException(id); throw new ResourceNotFoundException(id);
} }
private boolean isMember(AccountGroup group, IdentifiedUser user) private boolean isMember(GroupDescription.Internal group, IdentifiedUser user)
throws OrmException, ResourceNotFoundException { throws OrmException, ResourceNotFoundException {
AccountGroup.UUID groupUuid = group.getGroupUUID(); AccountGroup.UUID groupUuid = group.getGroupUUID();
try { try {

View File

@@ -15,6 +15,7 @@
package com.google.gerrit.server.group; package com.google.gerrit.server.group;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.DefaultInput; import com.google.gerrit.extensions.restapi.DefaultInput;
@@ -56,16 +57,15 @@ public class PutDescription implements RestModifyView<GroupResource, Input> {
input = new Input(); // Delete would set description to null. input = new Input(); // Delete would set description to null.
} }
AccountGroup accountGroup = resource.toAccountGroup(); GroupDescription.Internal internalGroup =
if (accountGroup == null) { resource.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
throw new MethodNotAllowedException(); if (!resource.getControl().isOwner()) {
} else if (!resource.getControl().isOwner()) {
throw new AuthException("Not group owner"); throw new AuthException("Not group owner");
} }
String newDescription = Strings.emptyToNull(input.description); String newDescription = Strings.emptyToNull(input.description);
if (!Objects.equals(accountGroup.getDescription(), newDescription)) { if (!Objects.equals(internalGroup.getDescription(), newDescription)) {
AccountGroup.UUID groupUuid = resource.getGroupUUID(); AccountGroup.UUID groupUuid = internalGroup.getGroupUUID();
try { try {
groupsUpdateProvider groupsUpdateProvider
.get() .get()

View File

@@ -15,6 +15,7 @@
package com.google.gerrit.server.group; package com.google.gerrit.server.group;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.errors.NameAlreadyUsedException; import com.google.gerrit.common.errors.NameAlreadyUsedException;
import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.AuthException;
@@ -52,9 +53,9 @@ public class PutName implements RestModifyView<GroupResource, Input> {
public String apply(GroupResource rsrc, Input input) public String apply(GroupResource rsrc, Input input)
throws MethodNotAllowedException, AuthException, BadRequestException, throws MethodNotAllowedException, AuthException, BadRequestException,
ResourceConflictException, ResourceNotFoundException, OrmException, IOException { ResourceConflictException, ResourceNotFoundException, OrmException, IOException {
if (rsrc.toAccountGroup() == null) { GroupDescription.Internal internalGroup =
throw new MethodNotAllowedException(); rsrc.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
} else if (!rsrc.getControl().isOwner()) { if (!rsrc.getControl().isOwner()) {
throw new AuthException("Not group owner"); throw new AuthException("Not group owner");
} else if (input == null || Strings.isNullOrEmpty(input.name)) { } else if (input == null || Strings.isNullOrEmpty(input.name)) {
throw new BadRequestException("name is required"); throw new BadRequestException("name is required");
@@ -64,15 +65,15 @@ public class PutName implements RestModifyView<GroupResource, Input> {
throw new BadRequestException("name is required"); throw new BadRequestException("name is required");
} }
if (rsrc.toAccountGroup().getName().equals(newName)) { if (internalGroup.getName().equals(newName)) {
return newName; return newName;
} }
renameGroup(rsrc.toAccountGroup(), newName); renameGroup(internalGroup, newName);
return newName; return newName;
} }
private void renameGroup(AccountGroup group, String newName) private void renameGroup(GroupDescription.Internal group, String newName)
throws ResourceConflictException, ResourceNotFoundException, OrmException, IOException { throws ResourceConflictException, ResourceNotFoundException, OrmException, IOException {
AccountGroup.UUID groupUuid = group.getGroupUUID(); AccountGroup.UUID groupUuid = group.getGroupUUID();
try { try {

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.server.group; package com.google.gerrit.server.group;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.common.GroupOptionsInfo; import com.google.gerrit.extensions.common.GroupOptionsInfo;
import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.AuthException;
@@ -44,10 +45,9 @@ public class PutOptions implements RestModifyView<GroupResource, GroupOptionsInf
public GroupOptionsInfo apply(GroupResource resource, GroupOptionsInfo input) public GroupOptionsInfo apply(GroupResource resource, GroupOptionsInfo input)
throws MethodNotAllowedException, AuthException, BadRequestException, throws MethodNotAllowedException, AuthException, BadRequestException,
ResourceNotFoundException, OrmException, IOException { ResourceNotFoundException, OrmException, IOException {
AccountGroup accountGroup = resource.toAccountGroup(); GroupDescription.Internal internalGroup =
if (accountGroup == null) { resource.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
throw new MethodNotAllowedException(); if (!resource.getControl().isOwner()) {
} else if (!resource.getControl().isOwner()) {
throw new AuthException("Not group owner"); throw new AuthException("Not group owner");
} }
@@ -58,8 +58,8 @@ public class PutOptions implements RestModifyView<GroupResource, GroupOptionsInf
input.visibleToAll = false; input.visibleToAll = false;
} }
if (accountGroup.isVisibleToAll() != input.visibleToAll) { if (internalGroup.isVisibleToAll() != input.visibleToAll) {
AccountGroup.UUID groupUuid = accountGroup.getGroupUUID(); AccountGroup.UUID groupUuid = internalGroup.getGroupUUID();
try { try {
groupsUpdateProvider groupsUpdateProvider
.get() .get()

View File

@@ -61,10 +61,9 @@ public class PutOwner implements RestModifyView<GroupResource, Input> {
public GroupInfo apply(GroupResource resource, Input input) public GroupInfo apply(GroupResource resource, Input input)
throws ResourceNotFoundException, MethodNotAllowedException, AuthException, throws ResourceNotFoundException, MethodNotAllowedException, AuthException,
BadRequestException, UnprocessableEntityException, OrmException, IOException { BadRequestException, UnprocessableEntityException, OrmException, IOException {
AccountGroup accountGroup = resource.toAccountGroup(); GroupDescription.Internal internalGroup =
if (accountGroup == null) { resource.asInternalGroup().orElseThrow(MethodNotAllowedException::new);
throw new MethodNotAllowedException(); if (!resource.getControl().isOwner()) {
} else if (!resource.getControl().isOwner()) {
throw new AuthException("Not group owner"); throw new AuthException("Not group owner");
} }
@@ -73,8 +72,8 @@ public class PutOwner implements RestModifyView<GroupResource, Input> {
} }
GroupDescription.Basic owner = groupsCollection.parse(input.owner); GroupDescription.Basic owner = groupsCollection.parse(input.owner);
if (!accountGroup.getOwnerGroupUUID().equals(owner.getGroupUUID())) { if (!internalGroup.getOwnerGroupUUID().equals(owner.getGroupUUID())) {
AccountGroup.UUID groupUuid = resource.getGroupUUID(); AccountGroup.UUID groupUuid = internalGroup.getGroupUUID();
try { try {
groupsUpdateProvider groupsUpdateProvider
.get() .get()

View File

@@ -16,7 +16,6 @@ package com.google.gerrit.server.mail.send;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.gerrit.common.data.GroupDescription; import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupDescriptions;
import com.google.gerrit.common.data.GroupReference; import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.index.query.Predicate; import com.google.gerrit.index.query.Predicate;
@@ -175,12 +174,12 @@ public class ProjectWatch {
continue; continue;
} }
AccountGroup ig = GroupDescriptions.toAccountGroup(group); if (!(group instanceof GroupDescription.Internal)) {
if (ig == null) {
// Non-internal groups cannot be expanded by the server. // Non-internal groups cannot be expanded by the server.
continue; continue;
} }
GroupDescription.Internal ig = (GroupDescription.Internal) group;
try { try {
args.groups.getMembers(db, ig.getGroupUUID()).forEach(matching.accounts::add); args.groups.getMembers(db, ig.getGroupUUID()).forEach(matching.accounts::add);
} catch (NoSuchGroupException e) { } catch (NoSuchGroupException e) {