diff options
Diffstat (limited to 'gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java')
-rw-r--r-- | gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java | 413 |
1 files changed, 0 insertions, 413 deletions
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java deleted file mode 100644 index ad475b32d3..0000000000 --- a/gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.gerrit.server.group; - -import static com.google.common.collect.ImmutableSet.toImmutableSet; -import static com.google.gerrit.server.group.Groups.getExistingGroupFromReviewDb; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.gerrit.audit.AuditService; -import com.google.gerrit.common.Nullable; -import com.google.gerrit.common.errors.NameAlreadyUsedException; -import com.google.gerrit.common.errors.NoSuchGroupException; -import com.google.gerrit.reviewdb.client.Account; -import com.google.gerrit.reviewdb.client.AccountGroup; -import com.google.gerrit.reviewdb.client.AccountGroupById; -import com.google.gerrit.reviewdb.client.AccountGroupMember; -import com.google.gerrit.reviewdb.client.AccountGroupName; -import com.google.gerrit.reviewdb.server.ReviewDb; -import com.google.gerrit.server.GerritPersonIdent; -import com.google.gerrit.server.IdentifiedUser; -import com.google.gerrit.server.account.GroupCache; -import com.google.gerrit.server.account.GroupIncludeCache; -import com.google.gerrit.server.git.RenameGroupOp; -import com.google.gwtorm.server.OrmException; -import com.google.inject.Inject; -import com.google.inject.assistedinject.Assisted; -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -import org.eclipse.jgit.lib.PersonIdent; - -/** - * A database accessor for write calls related to groups. - * - * <p>All calls which write group related details to the database (either ReviewDb or NoteDb) are - * gathered here. Other classes should always use this class instead of accessing the database - * directly. There are a few exceptions though: schema classes, wrapper classes, and classes - * executed during init. The latter ones should use {@code GroupsOnInit} instead. - * - * <p>If not explicitly stated, all methods of this class refer to <em>internal</em> groups. - */ -public class GroupsUpdate { - public interface Factory { - /** - * Creates a {@code GroupsUpdate} which uses the identity of the specified user to mark database - * modifications executed by it. For NoteDb, this identity is used as author and committer for - * all related commits. - * - * <p><strong>Note</strong>: Please use this method with care and rather consider to use the - * correct annotation on the provider of a {@code GroupsUpdate} instead. - * - * @param currentUser the user to which modifications should be attributed, or {@code null} if - * the Gerrit server identity should be used - */ - GroupsUpdate create(@Nullable IdentifiedUser currentUser); - } - - private final Groups groups; - private final GroupCache groupCache; - private final GroupIncludeCache groupIncludeCache; - private final AuditService auditService; - private final RenameGroupOp.Factory renameGroupOpFactory; - @Nullable private final IdentifiedUser currentUser; - private final PersonIdent committerIdent; - - @Inject - GroupsUpdate( - Groups groups, - GroupCache groupCache, - GroupIncludeCache groupIncludeCache, - AuditService auditService, - RenameGroupOp.Factory renameGroupOpFactory, - @GerritPersonIdent PersonIdent serverIdent, - @Assisted @Nullable IdentifiedUser currentUser) { - this.groups = groups; - this.groupCache = groupCache; - this.groupIncludeCache = groupIncludeCache; - this.auditService = auditService; - this.renameGroupOpFactory = renameGroupOpFactory; - this.currentUser = currentUser; - committerIdent = getCommitterIdent(serverIdent, currentUser); - } - - private static PersonIdent getCommitterIdent( - PersonIdent serverIdent, @Nullable IdentifiedUser currentUser) { - return currentUser != null ? createPersonIdent(serverIdent, currentUser) : serverIdent; - } - - private static PersonIdent createPersonIdent(PersonIdent ident, IdentifiedUser user) { - return user.newCommitterIdent(ident.getWhen(), ident.getTimeZone()); - } - - /** - * Adds/Creates the specified group for the specified members (accounts). - * - * @param db the {@code ReviewDb} instance to update - * @param group the group to add - * @param memberIds the IDs of the accounts which should be members of the created group - * @throws OrmException if an error occurs while reading/writing from/to ReviewDb - * @throws IOException if the cache entry of one of the new members couldn't be invalidated, or - * the new group couldn't be indexed - */ - public void addGroup(ReviewDb db, AccountGroup group, Set<Account.Id> memberIds) - throws OrmException, IOException { - addNewGroup(db, group); - addNewGroupMembers(db, group, memberIds); - groupCache.onCreateGroup(group); - } - - /** - * Adds the specified group. - * - * <p><strong>Note</strong>: This method doesn't update the index! It just adds the group to the - * database. Use this method with care. - * - * @param db the {@code ReviewDb} instance to update - * @param group the group to add - * @throws OrmException if an error occurs while reading/writing from/to ReviewDb - */ - public static void addNewGroup(ReviewDb db, AccountGroup group) throws OrmException { - AccountGroupName gn = new AccountGroupName(group); - // first insert the group name to validate that the group name hasn't - // already been used to create another group - db.accountGroupNames().insert(ImmutableList.of(gn)); - db.accountGroups().insert(ImmutableList.of(group)); - } - - /** - * Updates the specified group. - * - * @param db the {@code ReviewDb} instance to update - * @param groupUuid the UUID of the group to update - * @param groupConsumer a {@code Consumer} which performs the desired updates on the group - * @throws OrmException if an error occurs while reading/writing from/to ReviewDb - * @throws IOException if the cache entry for the group couldn't be invalidated - * @throws NoSuchGroupException if the specified group doesn't exist - */ - public void updateGroup( - ReviewDb db, AccountGroup.UUID groupUuid, Consumer<AccountGroup> groupConsumer) - throws OrmException, IOException, NoSuchGroupException { - AccountGroup updatedGroup = updateGroupInDb(db, groupUuid, groupConsumer); - groupCache.evict(updatedGroup.getGroupUUID(), updatedGroup.getId(), updatedGroup.getNameKey()); - } - - @VisibleForTesting - public AccountGroup updateGroupInDb( - ReviewDb db, AccountGroup.UUID groupUuid, Consumer<AccountGroup> groupConsumer) - throws OrmException, NoSuchGroupException { - AccountGroup group = getExistingGroupFromReviewDb(db, groupUuid); - groupConsumer.accept(group); - db.accountGroups().update(ImmutableList.of(group)); - return group; - } - - /** - * Renames the specified group. - * - * @param db the {@code ReviewDb} instance to update - * @param groupUuid the UUID of the group to rename - * @param newName the new name of the group - * @throws OrmException if an error occurs while reading/writing from/to ReviewDb - * @throws IOException if the cache entry for the group couldn't be invalidated - * @throws NoSuchGroupException if the specified group doesn't exist - * @throws NameAlreadyUsedException if another group has the name {@code newName} - */ - public void renameGroup(ReviewDb db, AccountGroup.UUID groupUuid, AccountGroup.NameKey newName) - throws OrmException, IOException, NameAlreadyUsedException, NoSuchGroupException { - AccountGroup group = getExistingGroupFromReviewDb(db, groupUuid); - AccountGroup.NameKey oldName = group.getNameKey(); - - try { - AccountGroupName id = new AccountGroupName(newName, group.getId()); - db.accountGroupNames().insert(ImmutableList.of(id)); - } catch (OrmException e) { - AccountGroupName other = db.accountGroupNames().get(newName); - if (other != null) { - // If we are using this identity, don't report the exception. - if (other.getId().equals(group.getId())) { - return; - } - - // Otherwise, someone else has this identity. - throw new NameAlreadyUsedException("group with name " + newName + " already exists"); - } - throw e; - } - - group.setNameKey(newName); - db.accountGroups().update(ImmutableList.of(group)); - - db.accountGroupNames().deleteKeys(ImmutableList.of(oldName)); - - groupCache.evictAfterRename(oldName); - groupCache.evict(group.getGroupUUID(), group.getId(), group.getNameKey()); - - @SuppressWarnings("unused") - Future<?> possiblyIgnoredError = - renameGroupOpFactory - .create(committerIdent, groupUuid, oldName.get(), newName.get()) - .start(0, TimeUnit.MILLISECONDS); - } - - /** - * Adds an account as member to a group. The account is only added as a new member if it isn't - * already a member of the group. - * - * <p><strong>Note</strong>: This method doesn't check whether the account exists! - * - * @param db the {@code ReviewDb} instance to update - * @param groupUuid the UUID of the group - * @param accountId the ID of the account to add - * @throws OrmException if an error occurs while reading/writing from/to ReviewDb - * @throws IOException if the cache entry of the new member couldn't be invalidated - * @throws NoSuchGroupException if the specified group doesn't exist - */ - public void addGroupMember(ReviewDb db, AccountGroup.UUID groupUuid, Account.Id accountId) - throws OrmException, IOException, NoSuchGroupException { - addGroupMembers(db, groupUuid, ImmutableSet.of(accountId)); - } - - /** - * Adds several accounts as members to a group. Only accounts which currently aren't members of - * the group are added. - * - * <p><strong>Note</strong>: This method doesn't check whether the accounts exist! - * - * @param db the {@code ReviewDb} instance to update - * @param groupUuid the UUID of the group - * @param accountIds a set of IDs of accounts to add - * @throws OrmException if an error occurs while reading/writing from/to ReviewDb - * @throws IOException if the group or one of the new members couldn't be indexed - * @throws NoSuchGroupException if the specified group doesn't exist - */ - public void addGroupMembers(ReviewDb db, AccountGroup.UUID groupUuid, Set<Account.Id> accountIds) - throws OrmException, IOException, NoSuchGroupException { - AccountGroup group = getExistingGroupFromReviewDb(db, groupUuid); - Set<Account.Id> newMemberIds = new HashSet<>(); - for (Account.Id accountId : accountIds) { - boolean isMember = groups.isMember(db, groupUuid, accountId); - if (!isMember) { - newMemberIds.add(accountId); - } - } - - if (newMemberIds.isEmpty()) { - return; - } - - addNewGroupMembers(db, group, newMemberIds); - } - - private void addNewGroupMembers(ReviewDb db, AccountGroup group, Set<Account.Id> newMemberIds) - throws OrmException, IOException { - Set<AccountGroupMember> newMembers = - newMemberIds.stream() - .map(accountId -> new AccountGroupMember.Key(accountId, group.getId())) - .map(AccountGroupMember::new) - .collect(toImmutableSet()); - - if (currentUser != null) { - auditService.dispatchAddAccountsToGroup(currentUser.getAccountId(), newMembers); - } - db.accountGroupMembers().insert(newMembers); - groupCache.evict(group.getGroupUUID(), group.getId(), group.getNameKey()); - for (AccountGroupMember newMember : newMembers) { - groupIncludeCache.evictGroupsWithMember(newMember.getAccountId()); - } - } - - /** - * Removes several members (accounts) from a group. Only accounts which currently are members of - * the group are removed. - * - * @param db the {@code ReviewDb} instance to update - * @param groupUuid the UUID of the group - * @param accountIds a set of IDs of accounts to remove - * @throws OrmException if an error occurs while reading/writing from/to ReviewDb - * @throws IOException if the group or one of the removed members couldn't be indexed - * @throws NoSuchGroupException if the specified group doesn't exist - */ - public void removeGroupMembers( - ReviewDb db, AccountGroup.UUID groupUuid, Set<Account.Id> accountIds) - throws OrmException, IOException, NoSuchGroupException { - AccountGroup group = getExistingGroupFromReviewDb(db, groupUuid); - AccountGroup.Id groupId = group.getId(); - Set<AccountGroupMember> membersToRemove = new HashSet<>(); - for (Account.Id accountId : accountIds) { - boolean isMember = groups.isMember(db, groupUuid, accountId); - if (isMember) { - AccountGroupMember.Key key = new AccountGroupMember.Key(accountId, groupId); - membersToRemove.add(new AccountGroupMember(key)); - } - } - - if (membersToRemove.isEmpty()) { - return; - } - - if (currentUser != null) { - auditService.dispatchDeleteAccountsFromGroup(currentUser.getAccountId(), membersToRemove); - } - db.accountGroupMembers().delete(membersToRemove); - groupCache.evict(group.getGroupUUID(), group.getId(), group.getNameKey()); - for (AccountGroupMember member : membersToRemove) { - groupIncludeCache.evictGroupsWithMember(member.getAccountId()); - } - } - - /** - * Adds several groups as subgroups to a group. Only groups which currently aren't subgroups of - * the group are added. - * - * <p>The parent group must be an internal group whereas the subgroups can either be internal or - * external groups. - * - * <p><strong>Note</strong>: This method doesn't check whether the subgroups exist! - * - * @param db the {@code ReviewDb} instance to update - * @param parentGroupUuid the UUID of the parent group - * @param subgroupUuids a set of IDs of the groups to add as subgroups - * @throws OrmException if an error occurs while reading/writing from/to ReviewDb - * @throws IOException if the parent group couldn't be indexed - * @throws NoSuchGroupException if the specified parent group doesn't exist - */ - public void addSubgroups( - ReviewDb db, AccountGroup.UUID parentGroupUuid, Set<AccountGroup.UUID> subgroupUuids) - throws OrmException, NoSuchGroupException, IOException { - AccountGroup parentGroup = getExistingGroupFromReviewDb(db, parentGroupUuid); - AccountGroup.Id parentGroupId = parentGroup.getId(); - Set<AccountGroupById> newSubgroups = new HashSet<>(); - for (AccountGroup.UUID includedGroupUuid : subgroupUuids) { - boolean isSubgroup = groups.isSubgroup(db, parentGroupUuid, includedGroupUuid); - if (!isSubgroup) { - AccountGroupById.Key key = new AccountGroupById.Key(parentGroupId, includedGroupUuid); - newSubgroups.add(new AccountGroupById(key)); - } - } - - if (newSubgroups.isEmpty()) { - return; - } - - if (currentUser != null) { - auditService.dispatchAddGroupsToGroup(currentUser.getAccountId(), newSubgroups); - } - db.accountGroupById().insert(newSubgroups); - groupCache.evict(parentGroup.getGroupUUID(), parentGroup.getId(), parentGroup.getNameKey()); - for (AccountGroupById newIncludedGroup : newSubgroups) { - groupIncludeCache.evictParentGroupsOf(newIncludedGroup.getIncludeUUID()); - } - groupIncludeCache.evictSubgroupsOf(parentGroupUuid); - } - - /** - * Removes several subgroups from a parent group. Only groups which currently are subgroups of the - * group are removed. - * - * <p>The parent group must be an internal group whereas the subgroups can either be internal or - * external groups. - * - * @param db the {@code ReviewDb} instance to update - * @param parentGroupUuid the UUID of the parent group - * @param subgroupUuids a set of IDs of the subgroups to remove from the parent group - * @throws OrmException if an error occurs while reading/writing from/to ReviewDb - * @throws IOException if the parent group couldn't be indexed - * @throws NoSuchGroupException if the specified parent group doesn't exist - */ - public void removeSubgroups( - ReviewDb db, AccountGroup.UUID parentGroupUuid, Set<AccountGroup.UUID> subgroupUuids) - throws OrmException, NoSuchGroupException, IOException { - AccountGroup parentGroup = getExistingGroupFromReviewDb(db, parentGroupUuid); - AccountGroup.Id parentGroupId = parentGroup.getId(); - Set<AccountGroupById> subgroupsToRemove = new HashSet<>(); - for (AccountGroup.UUID subgroupUuid : subgroupUuids) { - boolean isSubgroup = groups.isSubgroup(db, parentGroupUuid, subgroupUuid); - if (isSubgroup) { - AccountGroupById.Key key = new AccountGroupById.Key(parentGroupId, subgroupUuid); - subgroupsToRemove.add(new AccountGroupById(key)); - } - } - - if (subgroupsToRemove.isEmpty()) { - return; - } - - if (currentUser != null) { - auditService.dispatchDeleteGroupsFromGroup(currentUser.getAccountId(), subgroupsToRemove); - } - db.accountGroupById().delete(subgroupsToRemove); - groupCache.evict(parentGroup.getGroupUUID(), parentGroup.getId(), parentGroup.getNameKey()); - for (AccountGroupById groupToRemove : subgroupsToRemove) { - groupIncludeCache.evictParentGroupsOf(groupToRemove.getIncludeUUID()); - } - groupIncludeCache.evictSubgroupsOf(parentGroupUuid); - } -} |