Disallow reading groups from ReviewDb if noteDb.groups.read == true

With noteDb.groups.read == true groups should only be read from NoteDb.
Reading groups from ReviewDb with this setting is an error. With this
change any read access to the group tables in ReviewDb throws an
exception when reading groups from NoteDb is configured.

There are a few places where group are read from ReviewDb although
noteDb.groups.read is set to true. Fixing these is outside the scope of
this change. For now TODOs are added and the ReviewDb instance is
unwrapped where needed.

Change-Id: I219ac49f8edb9daac58e826667b0fe7ec68db0df
Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
Edwin Kempin 2017-11-17 13:14:31 +01:00
parent 945ae514f5
commit b4e63f9462
6 changed files with 961 additions and 35 deletions

View File

@ -0,0 +1,310 @@
// 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.reviewdb.server;
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.AccountGroupByIdAud;
import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
import com.google.gerrit.reviewdb.client.AccountGroupName;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
public class DisallowReadFromGroupsReviewDbWrapper extends ReviewDbWrapper {
private static final String MSG = "This table has been migrated to NoteDb";
private final Groups groups;
private final GroupNames groupNames;
private final GroupMembers groupMembers;
private final GroupMemberAudits groupMemberAudits;
private final ByIds byIds;
private final ByIdAudits byIdAudits;
public DisallowReadFromGroupsReviewDbWrapper(ReviewDb db) {
super(db);
groups = new Groups(delegate.accountGroups());
groupNames = new GroupNames(delegate.accountGroupNames());
groupMembers = new GroupMembers(delegate.accountGroupMembers());
groupMemberAudits = new GroupMemberAudits(delegate.accountGroupMembersAudit());
byIds = new ByIds(delegate.accountGroupById());
byIdAudits = new ByIdAudits(delegate.accountGroupByIdAud());
}
public ReviewDb unsafeGetDelegate() {
return delegate;
}
@Override
public AccountGroupAccess accountGroups() {
return groups;
}
@Override
public AccountGroupNameAccess accountGroupNames() {
return groupNames;
}
@Override
public AccountGroupMemberAccess accountGroupMembers() {
return groupMembers;
}
@Override
public AccountGroupMemberAuditAccess accountGroupMembersAudit() {
return groupMemberAudits;
}
@Override
public AccountGroupByIdAccess accountGroupById() {
return byIds;
}
@Override
public AccountGroupByIdAudAccess accountGroupByIdAud() {
return byIdAudits;
}
private static class Groups extends AccountGroupAccessWrapper {
protected Groups(AccountGroupAccess delegate) {
super(delegate);
}
@Override
public ResultSet<AccountGroup> iterateAllEntities() {
throw new UnsupportedOperationException(MSG);
}
@SuppressWarnings("deprecation")
@Override
public com.google.common.util.concurrent.CheckedFuture<AccountGroup, OrmException> getAsync(
AccountGroup.Id key) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroup> get(Iterable<AccountGroup.Id> keys) {
throw new UnsupportedOperationException(MSG);
}
@Override
public AccountGroup get(AccountGroup.Id id) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroup> byUUID(AccountGroup.UUID uuid) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroup> all() {
throw new UnsupportedOperationException(MSG);
}
}
private static class GroupNames extends AccountGroupNameAccessWrapper {
protected GroupNames(AccountGroupNameAccess delegate) {
super(delegate);
}
@Override
public ResultSet<AccountGroupName> iterateAllEntities() {
throw new UnsupportedOperationException(MSG);
}
@SuppressWarnings("deprecation")
@Override
public com.google.common.util.concurrent.CheckedFuture<AccountGroupName, OrmException> getAsync(
AccountGroup.NameKey key) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupName> get(Iterable<AccountGroup.NameKey> keys) {
throw new UnsupportedOperationException(MSG);
}
@Override
public AccountGroupName get(AccountGroup.NameKey name) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupName> all() {
throw new UnsupportedOperationException(MSG);
}
}
private static class GroupMembers extends AccountGroupMemberAccessWrapper {
protected GroupMembers(AccountGroupMemberAccess delegate) {
super(delegate);
}
@Override
public ResultSet<AccountGroupMember> iterateAllEntities() {
throw new UnsupportedOperationException(MSG);
}
@SuppressWarnings("deprecation")
@Override
public com.google.common.util.concurrent.CheckedFuture<AccountGroupMember, OrmException>
getAsync(AccountGroupMember.Key key) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupMember> get(Iterable<AccountGroupMember.Key> keys) {
throw new UnsupportedOperationException(MSG);
}
@Override
public AccountGroupMember get(AccountGroupMember.Key key) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupMember> byAccount(Account.Id id) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupMember> byGroup(AccountGroup.Id id) {
throw new UnsupportedOperationException(MSG);
}
}
private static class GroupMemberAudits extends AccountGroupMemberAuditAccessWrapper {
protected GroupMemberAudits(AccountGroupMemberAuditAccess delegate) {
super(delegate);
}
@Override
public ResultSet<AccountGroupMemberAudit> iterateAllEntities() {
throw new UnsupportedOperationException(MSG);
}
@SuppressWarnings("deprecation")
@Override
public com.google.common.util.concurrent.CheckedFuture<AccountGroupMemberAudit, OrmException>
getAsync(AccountGroupMemberAudit.Key key) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupMemberAudit> get(Iterable<AccountGroupMemberAudit.Key> keys) {
throw new UnsupportedOperationException(MSG);
}
@Override
public AccountGroupMemberAudit get(AccountGroupMemberAudit.Key key) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupMemberAudit> byGroupAccount(
AccountGroup.Id groupId, Account.Id accountId) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupMemberAudit> byGroup(AccountGroup.Id groupId) {
throw new UnsupportedOperationException(MSG);
}
}
private static class ByIds extends AccountGroupByIdAccessWrapper {
protected ByIds(AccountGroupByIdAccess delegate) {
super(delegate);
}
@Override
public ResultSet<AccountGroupById> iterateAllEntities() {
throw new UnsupportedOperationException(MSG);
}
@SuppressWarnings("deprecation")
@Override
public com.google.common.util.concurrent.CheckedFuture<AccountGroupById, OrmException> getAsync(
AccountGroupById.Key key) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupById> get(Iterable<AccountGroupById.Key> keys) {
throw new UnsupportedOperationException(MSG);
}
@Override
public AccountGroupById get(AccountGroupById.Key key) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupById> byIncludeUUID(AccountGroup.UUID uuid) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupById> byGroup(AccountGroup.Id id) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupById> all() {
throw new UnsupportedOperationException(MSG);
}
}
private static class ByIdAudits extends AccountGroupByIdAudAccessWrapper {
protected ByIdAudits(AccountGroupByIdAudAccess delegate) {
super(delegate);
}
@Override
public ResultSet<AccountGroupByIdAud> iterateAllEntities() {
throw new UnsupportedOperationException(MSG);
}
@SuppressWarnings("deprecation")
@Override
public com.google.common.util.concurrent.CheckedFuture<AccountGroupByIdAud, OrmException>
getAsync(AccountGroupByIdAud.Key key) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupByIdAud> get(Iterable<AccountGroupByIdAud.Key> keys) {
throw new UnsupportedOperationException(MSG);
}
@Override
public AccountGroupByIdAud get(AccountGroupByIdAud.Key key) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupByIdAud> byGroupInclude(
AccountGroup.Id groupId, AccountGroup.UUID incGroupUUID) {
throw new UnsupportedOperationException(MSG);
}
@Override
public ResultSet<AccountGroupByIdAud> byGroup(AccountGroup.Id groupId) {
throw new UnsupportedOperationException(MSG);
}
}
}

View File

@ -43,7 +43,10 @@ public class ReviewDbUtil {
public static ReviewDb unwrapDb(ReviewDb db) {
if (db instanceof DisallowReadFromChangesReviewDbWrapper) {
return ((DisallowReadFromChangesReviewDbWrapper) db).unsafeGetDelegate();
return unwrapDb(((DisallowReadFromChangesReviewDbWrapper) db).unsafeGetDelegate());
}
if (db instanceof DisallowReadFromGroupsReviewDbWrapper) {
return unwrapDb(((DisallowReadFromGroupsReviewDbWrapper) db).unsafeGetDelegate());
}
return db;
}

View File

@ -17,6 +17,12 @@ package com.google.gerrit.reviewdb.server;
import static com.google.common.base.Preconditions.checkNotNull;
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.AccountGroupByIdAud;
import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
import com.google.gerrit.reviewdb.client.AccountGroupName;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchLineComment;
@ -679,4 +685,591 @@ public class ReviewDbWrapper implements ReviewDb {
return delegate.all();
}
}
public static class AccountGroupAccessWrapper implements AccountGroupAccess {
protected final AccountGroupAccess delegate;
protected AccountGroupAccessWrapper(AccountGroupAccess delegate) {
this.delegate = checkNotNull(delegate);
}
@Override
public String getRelationName() {
return delegate.getRelationName();
}
@Override
public int getRelationID() {
return delegate.getRelationID();
}
@Override
public ResultSet<AccountGroup> iterateAllEntities() throws OrmException {
return delegate.iterateAllEntities();
}
@Override
public AccountGroup.Id primaryKey(AccountGroup entity) {
return delegate.primaryKey(entity);
}
@Override
public Map<AccountGroup.Id, AccountGroup> toMap(Iterable<AccountGroup> c) {
return delegate.toMap(c);
}
@SuppressWarnings("deprecation")
@Override
public com.google.common.util.concurrent.CheckedFuture<AccountGroup, OrmException> getAsync(
AccountGroup.Id key) {
return delegate.getAsync(key);
}
@Override
public ResultSet<AccountGroup> get(Iterable<AccountGroup.Id> keys) throws OrmException {
return delegate.get(keys);
}
@Override
public void insert(Iterable<AccountGroup> instances) throws OrmException {
delegate.insert(instances);
}
@Override
public void update(Iterable<AccountGroup> instances) throws OrmException {
delegate.update(instances);
}
@Override
public void upsert(Iterable<AccountGroup> instances) throws OrmException {
delegate.upsert(instances);
}
@Override
public void deleteKeys(Iterable<AccountGroup.Id> keys) throws OrmException {
delegate.deleteKeys(keys);
}
@Override
public void delete(Iterable<AccountGroup> instances) throws OrmException {
delegate.delete(instances);
}
@Override
public void beginTransaction(AccountGroup.Id key) throws OrmException {
delegate.beginTransaction(key);
}
@Override
public AccountGroup atomicUpdate(AccountGroup.Id key, AtomicUpdate<AccountGroup> update)
throws OrmException {
return delegate.atomicUpdate(key, update);
}
@Override
public AccountGroup get(AccountGroup.Id id) throws OrmException {
return delegate.get(id);
}
@Override
public ResultSet<AccountGroup> byUUID(AccountGroup.UUID uuid) throws OrmException {
return delegate.byUUID(uuid);
}
@Override
public ResultSet<AccountGroup> all() throws OrmException {
return delegate.all();
}
}
public static class AccountGroupNameAccessWrapper implements AccountGroupNameAccess {
protected final AccountGroupNameAccess delegate;
protected AccountGroupNameAccessWrapper(AccountGroupNameAccess delegate) {
this.delegate = checkNotNull(delegate);
}
@Override
public String getRelationName() {
return delegate.getRelationName();
}
@Override
public int getRelationID() {
return delegate.getRelationID();
}
@Override
public ResultSet<AccountGroupName> iterateAllEntities() throws OrmException {
return delegate.iterateAllEntities();
}
@Override
public AccountGroup.NameKey primaryKey(AccountGroupName entity) {
return delegate.primaryKey(entity);
}
@Override
public Map<AccountGroup.NameKey, AccountGroupName> toMap(Iterable<AccountGroupName> c) {
return delegate.toMap(c);
}
@SuppressWarnings("deprecation")
@Override
public com.google.common.util.concurrent.CheckedFuture<AccountGroupName, OrmException> getAsync(
AccountGroup.NameKey key) {
return delegate.getAsync(key);
}
@Override
public ResultSet<AccountGroupName> get(Iterable<AccountGroup.NameKey> keys)
throws OrmException {
return delegate.get(keys);
}
@Override
public void insert(Iterable<AccountGroupName> instances) throws OrmException {
delegate.insert(instances);
}
@Override
public void update(Iterable<AccountGroupName> instances) throws OrmException {
delegate.update(instances);
}
@Override
public void upsert(Iterable<AccountGroupName> instances) throws OrmException {
delegate.upsert(instances);
}
@Override
public void deleteKeys(Iterable<AccountGroup.NameKey> keys) throws OrmException {
delegate.deleteKeys(keys);
}
@Override
public void delete(Iterable<AccountGroupName> instances) throws OrmException {
delegate.delete(instances);
}
@Override
public void beginTransaction(AccountGroup.NameKey key) throws OrmException {
delegate.beginTransaction(key);
}
@Override
public AccountGroupName atomicUpdate(
AccountGroup.NameKey key, AtomicUpdate<AccountGroupName> update) throws OrmException {
return delegate.atomicUpdate(key, update);
}
@Override
public AccountGroupName get(AccountGroup.NameKey name) throws OrmException {
return delegate.get(name);
}
@Override
public ResultSet<AccountGroupName> all() throws OrmException {
return delegate.all();
}
}
public static class AccountGroupMemberAccessWrapper implements AccountGroupMemberAccess {
protected final AccountGroupMemberAccess delegate;
protected AccountGroupMemberAccessWrapper(AccountGroupMemberAccess delegate) {
this.delegate = checkNotNull(delegate);
}
@Override
public String getRelationName() {
return delegate.getRelationName();
}
@Override
public int getRelationID() {
return delegate.getRelationID();
}
@Override
public ResultSet<AccountGroupMember> iterateAllEntities() throws OrmException {
return delegate.iterateAllEntities();
}
@Override
public AccountGroupMember.Key primaryKey(AccountGroupMember entity) {
return delegate.primaryKey(entity);
}
@Override
public Map<AccountGroupMember.Key, AccountGroupMember> toMap(Iterable<AccountGroupMember> c) {
return delegate.toMap(c);
}
@SuppressWarnings("deprecation")
@Override
public com.google.common.util.concurrent.CheckedFuture<AccountGroupMember, OrmException>
getAsync(AccountGroupMember.Key key) {
return delegate.getAsync(key);
}
@Override
public ResultSet<AccountGroupMember> get(Iterable<AccountGroupMember.Key> keys)
throws OrmException {
return delegate.get(keys);
}
@Override
public void insert(Iterable<AccountGroupMember> instances) throws OrmException {
delegate.insert(instances);
}
@Override
public void update(Iterable<AccountGroupMember> instances) throws OrmException {
delegate.update(instances);
}
@Override
public void upsert(Iterable<AccountGroupMember> instances) throws OrmException {
delegate.upsert(instances);
}
@Override
public void deleteKeys(Iterable<AccountGroupMember.Key> keys) throws OrmException {
delegate.deleteKeys(keys);
}
@Override
public void delete(Iterable<AccountGroupMember> instances) throws OrmException {
delegate.delete(instances);
}
@Override
public void beginTransaction(AccountGroupMember.Key key) throws OrmException {
delegate.beginTransaction(key);
}
@Override
public AccountGroupMember atomicUpdate(
AccountGroupMember.Key key, AtomicUpdate<AccountGroupMember> update) throws OrmException {
return delegate.atomicUpdate(key, update);
}
@Override
public AccountGroupMember get(AccountGroupMember.Key key) throws OrmException {
return delegate.get(key);
}
@Override
public ResultSet<AccountGroupMember> byAccount(Account.Id id) throws OrmException {
return delegate.byAccount(id);
}
@Override
public ResultSet<AccountGroupMember> byGroup(AccountGroup.Id id) throws OrmException {
return delegate.byGroup(id);
}
}
public static class AccountGroupMemberAuditAccessWrapper
implements AccountGroupMemberAuditAccess {
protected final AccountGroupMemberAuditAccess delegate;
protected AccountGroupMemberAuditAccessWrapper(AccountGroupMemberAuditAccess delegate) {
this.delegate = checkNotNull(delegate);
}
@Override
public String getRelationName() {
return delegate.getRelationName();
}
@Override
public int getRelationID() {
return delegate.getRelationID();
}
@Override
public ResultSet<AccountGroupMemberAudit> iterateAllEntities() throws OrmException {
return delegate.iterateAllEntities();
}
@Override
public AccountGroupMemberAudit.Key primaryKey(AccountGroupMemberAudit entity) {
return delegate.primaryKey(entity);
}
@Override
public Map<AccountGroupMemberAudit.Key, AccountGroupMemberAudit> toMap(
Iterable<AccountGroupMemberAudit> c) {
return delegate.toMap(c);
}
@SuppressWarnings("deprecation")
@Override
public com.google.common.util.concurrent.CheckedFuture<AccountGroupMemberAudit, OrmException>
getAsync(AccountGroupMemberAudit.Key key) {
return delegate.getAsync(key);
}
@Override
public ResultSet<AccountGroupMemberAudit> get(Iterable<AccountGroupMemberAudit.Key> keys)
throws OrmException {
return delegate.get(keys);
}
@Override
public void insert(Iterable<AccountGroupMemberAudit> instances) throws OrmException {
delegate.insert(instances);
}
@Override
public void update(Iterable<AccountGroupMemberAudit> instances) throws OrmException {
delegate.update(instances);
}
@Override
public void upsert(Iterable<AccountGroupMemberAudit> instances) throws OrmException {
delegate.upsert(instances);
}
@Override
public void deleteKeys(Iterable<AccountGroupMemberAudit.Key> keys) throws OrmException {
delegate.deleteKeys(keys);
}
@Override
public void delete(Iterable<AccountGroupMemberAudit> instances) throws OrmException {
delegate.delete(instances);
}
@Override
public void beginTransaction(AccountGroupMemberAudit.Key key) throws OrmException {
delegate.beginTransaction(key);
}
@Override
public AccountGroupMemberAudit atomicUpdate(
AccountGroupMemberAudit.Key key, AtomicUpdate<AccountGroupMemberAudit> update)
throws OrmException {
return delegate.atomicUpdate(key, update);
}
@Override
public AccountGroupMemberAudit get(AccountGroupMemberAudit.Key key) throws OrmException {
return delegate.get(key);
}
@Override
public ResultSet<AccountGroupMemberAudit> byGroupAccount(
AccountGroup.Id groupId, Account.Id accountId) throws OrmException {
return delegate.byGroupAccount(groupId, accountId);
}
@Override
public ResultSet<AccountGroupMemberAudit> byGroup(AccountGroup.Id groupId) throws OrmException {
return delegate.byGroup(groupId);
}
}
public static class AccountGroupByIdAccessWrapper implements AccountGroupByIdAccess {
protected final AccountGroupByIdAccess delegate;
protected AccountGroupByIdAccessWrapper(AccountGroupByIdAccess delegate) {
this.delegate = checkNotNull(delegate);
}
@Override
public String getRelationName() {
return delegate.getRelationName();
}
@Override
public int getRelationID() {
return delegate.getRelationID();
}
@Override
public ResultSet<AccountGroupById> iterateAllEntities() throws OrmException {
return delegate.iterateAllEntities();
}
@Override
public AccountGroupById.Key primaryKey(AccountGroupById entity) {
return delegate.primaryKey(entity);
}
@Override
public Map<AccountGroupById.Key, AccountGroupById> toMap(Iterable<AccountGroupById> c) {
return delegate.toMap(c);
}
@SuppressWarnings("deprecation")
@Override
public com.google.common.util.concurrent.CheckedFuture<AccountGroupById, OrmException> getAsync(
AccountGroupById.Key key) {
return delegate.getAsync(key);
}
@Override
public ResultSet<AccountGroupById> get(Iterable<AccountGroupById.Key> keys)
throws OrmException {
return delegate.get(keys);
}
@Override
public void insert(Iterable<AccountGroupById> instances) throws OrmException {
delegate.insert(instances);
}
@Override
public void update(Iterable<AccountGroupById> instances) throws OrmException {
delegate.update(instances);
}
@Override
public void upsert(Iterable<AccountGroupById> instances) throws OrmException {
delegate.upsert(instances);
}
@Override
public void deleteKeys(Iterable<AccountGroupById.Key> keys) throws OrmException {
delegate.deleteKeys(keys);
}
@Override
public void delete(Iterable<AccountGroupById> instances) throws OrmException {
delegate.delete(instances);
}
@Override
public void beginTransaction(AccountGroupById.Key key) throws OrmException {
delegate.beginTransaction(key);
}
@Override
public AccountGroupById atomicUpdate(
AccountGroupById.Key key, AtomicUpdate<AccountGroupById> update) throws OrmException {
return delegate.atomicUpdate(key, update);
}
@Override
public AccountGroupById get(AccountGroupById.Key key) throws OrmException {
return delegate.get(key);
}
@Override
public ResultSet<AccountGroupById> byIncludeUUID(AccountGroup.UUID uuid) throws OrmException {
return delegate.byIncludeUUID(uuid);
}
@Override
public ResultSet<AccountGroupById> byGroup(AccountGroup.Id id) throws OrmException {
return delegate.byGroup(id);
}
@Override
public ResultSet<AccountGroupById> all() throws OrmException {
return delegate.all();
}
}
public static class AccountGroupByIdAudAccessWrapper implements AccountGroupByIdAudAccess {
protected final AccountGroupByIdAudAccess delegate;
protected AccountGroupByIdAudAccessWrapper(AccountGroupByIdAudAccess delegate) {
this.delegate = checkNotNull(delegate);
}
@Override
public String getRelationName() {
return delegate.getRelationName();
}
@Override
public int getRelationID() {
return delegate.getRelationID();
}
@Override
public ResultSet<AccountGroupByIdAud> iterateAllEntities() throws OrmException {
return delegate.iterateAllEntities();
}
@Override
public AccountGroupByIdAud.Key primaryKey(AccountGroupByIdAud entity) {
return delegate.primaryKey(entity);
}
@Override
public Map<AccountGroupByIdAud.Key, AccountGroupByIdAud> toMap(
Iterable<AccountGroupByIdAud> c) {
return delegate.toMap(c);
}
@SuppressWarnings("deprecation")
@Override
public com.google.common.util.concurrent.CheckedFuture<AccountGroupByIdAud, OrmException>
getAsync(AccountGroupByIdAud.Key key) {
return delegate.getAsync(key);
}
@Override
public ResultSet<AccountGroupByIdAud> get(Iterable<AccountGroupByIdAud.Key> keys)
throws OrmException {
return delegate.get(keys);
}
@Override
public void insert(Iterable<AccountGroupByIdAud> instances) throws OrmException {
delegate.insert(instances);
}
@Override
public void update(Iterable<AccountGroupByIdAud> instances) throws OrmException {
delegate.update(instances);
}
@Override
public void upsert(Iterable<AccountGroupByIdAud> instances) throws OrmException {
delegate.upsert(instances);
}
@Override
public void deleteKeys(Iterable<AccountGroupByIdAud.Key> keys) throws OrmException {
delegate.deleteKeys(keys);
}
@Override
public void delete(Iterable<AccountGroupByIdAud> instances) throws OrmException {
delegate.delete(instances);
}
@Override
public void beginTransaction(AccountGroupByIdAud.Key key) throws OrmException {
delegate.beginTransaction(key);
}
@Override
public AccountGroupByIdAud atomicUpdate(
AccountGroupByIdAud.Key key, AtomicUpdate<AccountGroupByIdAud> update) throws OrmException {
return delegate.atomicUpdate(key, update);
}
@Override
public AccountGroupByIdAud get(AccountGroupByIdAud.Key key) throws OrmException {
return delegate.get(key);
}
@Override
public ResultSet<AccountGroupByIdAud> byGroupInclude(
AccountGroup.Id groupId, AccountGroup.UUID incGroupUUID) throws OrmException {
return delegate.byGroupInclude(groupId, incGroupUUID);
}
@Override
public ResultSet<AccountGroupByIdAud> byGroup(AccountGroup.Id groupId) throws OrmException {
return delegate.byGroup(groupId);
}
}
}

View File

@ -32,6 +32,7 @@ import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountGroupName;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.reviewdb.server.ReviewDbUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
@ -204,7 +205,9 @@ public class GroupsUpdate {
public InternalGroup createGroup(
ReviewDb db, InternalGroupCreation groupCreation, InternalGroupUpdate groupUpdate)
throws OrmException, IOException, ConfigInvalidException {
InternalGroup createdGroupInReviewDb = createGroupInReviewDb(db, groupCreation, groupUpdate);
// TODO(ekempin): Don't read groups from ReviewDb if reading groups from NoteDb is configured
InternalGroup createdGroupInReviewDb =
createGroupInReviewDb(ReviewDbUtil.unwrapDb(db), groupCreation, groupUpdate);
if (!groupsMigration.writeToNoteDb()) {
updateCachesOnGroupCreation(createdGroupInReviewDb);
@ -240,8 +243,10 @@ public class GroupsUpdate {
public UpdateResult updateGroupInDb(
ReviewDb db, AccountGroup.UUID groupUuid, InternalGroupUpdate groupUpdate)
throws OrmException, NoSuchGroupException, IOException, ConfigInvalidException {
AccountGroup group = getExistingGroupFromReviewDb(db, groupUuid);
UpdateResult reviewDbUpdateResult = updateGroupInReviewDb(db, group, groupUpdate);
// TODO(ekempin): Don't read groups from ReviewDb if reading groups from NoteDb is configured
AccountGroup group = getExistingGroupFromReviewDb(ReviewDbUtil.unwrapDb(db), groupUuid);
UpdateResult reviewDbUpdateResult =
updateGroupInReviewDb(ReviewDbUtil.unwrapDb(db), group, groupUpdate);
if (!groupsMigration.writeToNoteDb()) {
return reviewDbUpdateResult;

View File

@ -15,7 +15,9 @@
package com.google.gerrit.server.schema;
import com.google.gerrit.reviewdb.server.DisallowReadFromChangesReviewDbWrapper;
import com.google.gerrit.reviewdb.server.DisallowReadFromGroupsReviewDbWrapper;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.notedb.GroupsMigration;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
@ -26,48 +28,58 @@ import com.google.inject.Singleton;
public class NotesMigrationSchemaFactory implements SchemaFactory<ReviewDb> {
private final SchemaFactory<ReviewDb> delegate;
private final NotesMigration migration;
private final GroupsMigration groupsMigration;
@Inject
NotesMigrationSchemaFactory(
@ReviewDbFactory SchemaFactory<ReviewDb> delegate, NotesMigration migration) {
@ReviewDbFactory SchemaFactory<ReviewDb> delegate,
NotesMigration migration,
GroupsMigration groupsMigration) {
this.delegate = delegate;
this.migration = migration;
this.groupsMigration = groupsMigration;
}
@Override
public ReviewDb open() throws OrmException {
ReviewDb db = delegate.open();
if (!migration.readChanges()) {
return db;
if (migration.readChanges()) {
// There are two levels at which this class disables access to Changes and related tables,
// corresponding to two phases of the NoteDb migration:
//
// 1. When changes are read from NoteDb but some changes might still have their primary
// storage in ReviewDb, it is generally programmer error to read changes from ReviewDb.
// However, since ReviewDb is still the primary storage for most or all changes, we still
// need to support writing to ReviewDb. This behavior is accomplished by wrapping in a
// DisallowReadFromChangesReviewDbWrapper.
//
// Some codepaths might need to be able to read from ReviewDb if they really need to,
// because they need to operate on the underlying source of truth, for example when
// reading a change to determine its primary storage. To support this,
// ReviewDbUtil#unwrapDb can detect and unwrap databases of this type.
//
// 2. After all changes have their primary storage in NoteDb, we can completely shut off
// access to the change tables. At this point in the migration, we are by definition not
// using the ReviewDb tables at all; we could even delete the tables at this point, and
// Gerrit would continue to function.
//
// This is accomplished by setting the delegate ReviewDb *underneath*
// DisallowReadFromChanges to be a complete no-op, with NoChangesReviewDbWrapper. With
// this wrapper, all read operations return no results, and write operations silently do
// nothing. This wrapper is not a public class and nobody should ever attempt to unwrap
// it.
if (migration.disableChangeReviewDb()) {
db = new NoChangesReviewDbWrapper(db);
}
db = new DisallowReadFromChangesReviewDbWrapper(db);
}
// There are two levels at which this class disables access to Changes and related tables,
// corresponding to two phases of the NoteDb migration:
//
// 1. When changes are read from NoteDb but some changes might still have their primary storage
// in ReviewDb, it is generally programmer error to read changes from ReviewDb. However,
// since ReviewDb is still the primary storage for most or all changes, we still need to
// support writing to ReviewDb. This behavior is accomplished by wrapping in a
// DisallowReadFromChangesReviewDbWrapper.
//
// Some codepaths might need to be able to read from ReviewDb if they really need to, because
// they need to operate on the underlying source of truth, for example when reading a change
// to determine its primary storage. To support this, ReviewDbUtil#unwrapDb can detect and
// unwrap databases of this type.
//
// 2. After all changes have their primary storage in NoteDb, we can completely shut off access
// to the change tables. At this point in the migration, we are by definition not using the
// ReviewDb tables at all; we could even delete the tables at this point, and Gerrit would
// continue to function.
//
// This is accomplished by setting the delegate ReviewDb *underneath* DisallowReadFromChanges
// to be a complete no-op, with NoChangesReviewDbWrapper. With this wrapper, all read
// operations return no results, and write operations silently do nothing. This wrapper is
// not a public class and nobody should ever attempt to unwrap it.
if (migration.disableChangeReviewDb()) {
db = new NoChangesReviewDbWrapper(db);
if (groupsMigration.readFromNoteDb()) {
// If reading groups from NoteDb is configured, groups should not be read from ReviewDb.
// Make sure that any attempt to read a group from ReviewDb anyway fails with an exception.
db = new DisallowReadFromGroupsReviewDbWrapper(db);
}
return new DisallowReadFromChangesReviewDbWrapper(db);
return db;
}
}

View File

@ -27,7 +27,10 @@ public enum GroupNoteDbMode {
/** Writing new groups to NoteDb is enabled. */
WRITE(new GroupsMigration(true, false)),
/** Reading/writing groups from/to NoteDb is enabled. */
/**
* Reading/writing groups from/to NoteDb is enabled. Trying to read groups from ReviewDb throws an
* exception.
*/
READ_WRITE(new GroupsMigration(true, true));
private static final String ENV_VAR = "GERRIT_NOTEDB_GROUPS";