Migrate Move to PermissionBackend
Change-Id: Ice0bc9099f997e7c3c7d8cde03dd8434fa6c7e70
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java
index 36f8452..552d7a4 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java
@@ -163,7 +163,7 @@
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID(),
"refs/for/" + newBranch.get());
exception.expect(AuthException.class);
- exception.expectMessage("Move not permitted");
+ exception.expectMessage("move not permitted");
move(r.getChangeId(), newBranch.get());
}
@@ -179,7 +179,7 @@
r.getChange().change().getDest().get());
setApiUser(user);
exception.expect(AuthException.class);
- exception.expectMessage("Move not permitted");
+ exception.expectMessage("move not permitted");
move(r.getChangeId(), newBranch.get());
}
@@ -223,7 +223,7 @@
revision(r).review(new ReviewInput().label("Patch-Set-Lock", 1));
exception.expect(AuthException.class);
- exception.expectMessage("Move not permitted");
+ exception.expectMessage("move not permitted");
move(r.getChangeId(), newBranch.get());
}
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/restapi/AuthException.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/restapi/AuthException.java
index 1d4cda7..0b4f459 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/restapi/AuthException.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/restapi/AuthException.java
@@ -22,4 +22,12 @@
public AuthException(String msg) {
super(msg);
}
+
+ /**
+ * @param msg message to return to the client.
+ * @param cause cause of this exception.
+ */
+ public AuthException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Move.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Move.java
index 98b79d1..ffc0dc4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Move.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Move.java
@@ -33,10 +33,14 @@
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.ChangeUtil;
+import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.project.ChangeControl;
+import com.google.gerrit.server.permissions.ChangePermission;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackendException;
+import com.google.gerrit.server.permissions.RefPermission;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
@@ -57,6 +61,7 @@
@Singleton
public class Move extends RetryingRestModifyView<ChangeResource, MoveInput, ChangeInfo> {
+ private final PermissionBackend permissionBackend;
private final Provider<ReviewDb> dbProvider;
private final ChangeJson.Factory json;
private final GitRepositoryManager repoManager;
@@ -66,6 +71,7 @@
@Inject
Move(
+ PermissionBackend permissionBackend,
Provider<ReviewDb> dbProvider,
ChangeJson.Factory json,
GitRepositoryManager repoManager,
@@ -74,6 +80,7 @@
RetryHelper retryHelper,
PatchSetUtil psUtil) {
super(retryHelper);
+ this.permissionBackend = permissionBackend;
this.dbProvider = dbProvider;
this.json = json;
this.repoManager = repoManager;
@@ -84,22 +91,40 @@
@Override
protected ChangeInfo applyImpl(
- BatchUpdate.Factory updateFactory, ChangeResource req, MoveInput input)
- throws RestApiException, OrmException, UpdateException {
- ChangeControl control = req.getControl();
+ BatchUpdate.Factory updateFactory, ChangeResource rsrc, MoveInput input)
+ throws RestApiException, OrmException, UpdateException, PermissionBackendException {
+ Change change = rsrc.getChange();
+ Project.NameKey project = rsrc.getProject();
+ IdentifiedUser caller = rsrc.getUser();
input.destinationBranch = RefNames.fullName(input.destinationBranch);
- if (!control.canMoveTo(input.destinationBranch, dbProvider.get())) {
- throw new AuthException("Move not permitted");
+
+ if (change.getStatus().isClosed()) {
+ throw new ResourceConflictException("Change is " + ChangeUtil.status(change));
+ }
+
+ Branch.NameKey newDest = new Branch.NameKey(project, input.destinationBranch);
+ if (change.getDest().equals(newDest)) {
+ throw new ResourceConflictException("Change is already destined for the specified branch");
+ }
+
+ // Move requires abandoning this change, and creating a new change.
+ try {
+ rsrc.permissions().database(dbProvider).check(ChangePermission.ABANDON);
+ permissionBackend
+ .user(caller)
+ .database(dbProvider)
+ .ref(newDest)
+ .check(RefPermission.CREATE_CHANGE);
+ } catch (AuthException denied) {
+ throw new AuthException("move not permitted", denied);
}
try (BatchUpdate u =
- updateFactory.create(
- dbProvider.get(), req.getChange().getProject(), control.getUser(), TimeUtil.nowTs())) {
- u.addOp(req.getChange().getId(), new Op(input));
+ updateFactory.create(dbProvider.get(), project, caller, TimeUtil.nowTs())) {
+ u.addOp(change.getId(), new Op(input));
u.execute();
}
-
- return json.noOptions().format(req.getChange());
+ return json.noOptions().format(project, rsrc.getId());
}
private class Op implements BatchUpdateOp {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
index 16c63c8..0b4c199 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
@@ -252,11 +252,6 @@
&& !isPatchSetLocked(db);
}
- /** Can this user change the destination branch of this change to the new ref? */
- public boolean canMoveTo(String ref, ReviewDb db) throws OrmException {
- return getProjectControl().controlForRef(ref).canUpload() && canAbandon(db);
- }
-
/** Can this user publish this draft change or any draft patch set of this change? */
public boolean canPublish(final ReviewDb db) throws OrmException {
return (isOwner() || getRefControl().canPublishDrafts()) && isVisible(db);