Draft status patchset and change prefilter

Prefilters patchsets and change messages when generating ChangeDetails
based on whether or not the current user can see a draft status
patchset. Also prefilters changes based on draft change status and
user status in ChangeList. Clients will only receive patchsets or
changes that they can see.

Change-Id: I14434e7907fd23cb036cd231684b04b7983f2087
This commit is contained in:
Jason Tsay
2011-08-09 15:58:48 -07:00
committed by Mohan Zhang
parent 2c18a88823
commit cd58931fd8
4 changed files with 65 additions and 5 deletions

View File

@@ -188,6 +188,10 @@ public class ChangeDetail {
currentDetail = d;
}
public void setCurrentPatchSetId(final PatchSet.Id id) {
currentPatchSetId = id;
}
public String getDescription() {
return currentDetail != null ? currentDetail.getInfo().getMessage() : "";
}

View File

@@ -338,6 +338,9 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
final ArrayList<ChangeInfo> list = new ArrayList<ChangeInfo>();
final ResultSet<Change> rs = query(db, slim, pos);
for (final Change c : rs) {
if (!canRead(c, db)) {
continue;
}
final ChangeInfo ci = new ChangeInfo(c);
ac.want(ci.getOwner());
ci.setStarred(starred.contains(ci.getId()));

View File

@@ -32,6 +32,7 @@ import com.google.gerrit.reviewdb.RevId;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountInfoCacheFactory;
import com.google.gerrit.server.config.GerritServerConfig;
@@ -42,6 +43,7 @@ import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.workflow.CategoryFunction;
import com.google.gerrit.server.workflow.FunctionState;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.ResultSet;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@@ -74,6 +76,7 @@ public class ChangeDetailFactory extends Handler<ChangeDetail> {
private ChangeDetail detail;
private ChangeControl control;
private Map<PatchSet.Id, PatchSet> patchsetsById;
private final MergeOp.Factory opFactory;
private boolean testMerge;
@@ -142,6 +145,7 @@ public class ChangeDetailFactory extends Handler<ChangeDetail> {
detail.setSubmitRecords(submitRecords);
}
patchsetsById = new HashMap<PatchSet.Id, PatchSet>();
loadPatchSets();
loadMessages();
if (change.currentPatchSetId() != null) {
@@ -153,11 +157,34 @@ public class ChangeDetailFactory extends Handler<ChangeDetail> {
}
private void loadPatchSets() throws OrmException {
detail.setPatchSets(db.patchSets().byChange(changeId).toList());
ResultSet<PatchSet> source = db.patchSets().byChange(changeId);
List<PatchSet> patches = new ArrayList<PatchSet>();
CurrentUser user = control.getCurrentUser();
for (PatchSet ps : source) {
if (control.isPatchVisible(ps, db)) {
patches.add(ps);
}
patchsetsById.put(ps.getId(), ps);
}
detail.setPatchSets(patches);
}
private void loadMessages() throws OrmException {
detail.setMessages(db.changeMessages().byChange(changeId).toList());
ResultSet<ChangeMessage> source = db.changeMessages().byChange(changeId);
List<ChangeMessage> msgList = new ArrayList<ChangeMessage>();
for (ChangeMessage msg : source) {
PatchSet.Id id = msg.getPatchSetId();
if (id != null) {
PatchSet ps = patchsetsById.get(msg.getPatchSetId());
if (control.isPatchVisible(ps, db)) {
msgList.add(msg);
}
} else {
// Not guaranteed to have a non-null patchset id, so just display it.
msgList.add(msg);
}
}
detail.setMessages(msgList);
for (final ChangeMessage m : detail.getMessages()) {
aic.want(m.getAuthor());
}
@@ -213,11 +240,13 @@ public class ChangeDetailFactory extends Handler<ChangeDetail> {
private void loadCurrentPatchSet() throws OrmException,
NoSuchEntityException, PatchSetInfoNotAvailableException,
NoSuchChangeException {
final PatchSet.Id psId = detail.getChange().currentPatchSetId();
final PatchSet currentPatch = findCurrentOrLatestPatchSet();
final PatchSet.Id psId = currentPatch.getId();
final PatchSetDetailFactory loader = patchSetDetail.create(null, psId, null);
loader.patchSet = detail.getCurrentPatchSet();
loader.patchSet = currentPatch;
loader.control = control;
detail.setCurrentPatchSetDetail(loader.call());
detail.setCurrentPatchSetId(psId);
final HashSet<Change.Id> changesToGet = new HashSet<Change.Id>();
final HashMap<Change.Id,PatchSet.Id> ancestorPatchIds =
@@ -272,6 +301,22 @@ public class ChangeDetailFactory extends Handler<ChangeDetail> {
detail.setNeededBy(neededBy);
}
private PatchSet findCurrentOrLatestPatchSet() {
PatchSet currentPatch = detail.getCurrentPatchSet();
// If the current patch set is a draft and user can't see it, set the
// current patch set to whatever the latest one is
if (currentPatch == null) {
List<PatchSet> patchSets = detail.getPatchSets();
if (!detail.getPatchSets().isEmpty()) {
currentPatch = patchSets.get(patchSets.size() - 1);
} else {
// Shouldn't happen, change shouldn't be visible if all the patchsets
// are drafts
}
}
return currentPatch;
}
private ChangeInfo newChangeInfo(final Change ac,
Map<Change.Id,PatchSet.Id> ancestorPatchIds) {
aic.want(ac.getOwner());

View File

@@ -172,6 +172,14 @@ public class ChangeControl {
return getRefControl().isVisible();
}
/** Can this user see the given patchset? */
public boolean isPatchVisible(PatchSet ps, ReviewDb db) throws OrmException {
if (ps.isDraft() && !isDraftVisible(db)) {
return false;
}
return isVisible(db);
}
/** Can this user abandon this change? */
public boolean canAbandon() {
return isOwner() // owner (aka creator) of the change can abandon