Fix /detail caching to include project ACLs and user id

The information included in /changes/{id}/detail can be dependent
on the calling user and on the project access controls and rules.pl
versions. Include these values as part of the ETag computation used
to cache the detailed change information.

Bug: issue 2079
Change-Id: I88b3f53394b245d4ce2c618d4f1265c67bab635b
This commit is contained in:
Shawn Pearce
2013-08-23 15:18:57 -07:00
parent 8e9616b7a3
commit 2de365c05f

View File

@@ -14,13 +14,21 @@
package com.google.gerrit.server.change;
import com.google.common.base.Objects;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestResource.HasETag;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.TypeLiteral;
import org.eclipse.jgit.lib.ObjectId;
public class ChangeResource implements RestResource, HasETag {
public static final TypeLiteral<RestView<ChangeResource>> CHANGE_KIND =
new TypeLiteral<RestView<ChangeResource>>() {};
@@ -45,8 +53,20 @@ public class ChangeResource implements RestResource, HasETag {
@Override
public String getETag() {
return String.format("%x-%x",
getChange().getLastUpdatedOn().getTime(),
getChange().getRowVersion());
CurrentUser user = control.getCurrentUser();
Hasher h = Hashing.md5().newHasher()
.putLong(getChange().getLastUpdatedOn().getTime())
.putInt(getChange().getRowVersion())
.putInt(user instanceof IdentifiedUser
? ((IdentifiedUser) user).getAccountId().get()
: 0);
byte[] buf = new byte[20];
for (ProjectState p : control.getProjectControl().getProjectState().tree()) {
ObjectId id = p.getConfig().getRevision();
Objects.firstNonNull(id, ObjectId.zeroId()).copyRawTo(buf, 0);
h.putBytes(buf);
}
return h.hash().toString();
}
}