Merge "Add REST API to toggle starred change state" into stable-2.8

This commit is contained in:
Shawn Pearce 2013-11-09 03:35:53 +00:00 committed by Gerrit Code Review
commit f4a8de43a6
14 changed files with 467 additions and 153 deletions

View File

@ -921,6 +921,84 @@ link:#diff-preferences-info[DiffPreferencesInfo] entity.
}
----
Get Starred Changes
~~~~~~~~~~~~~~~~~~~
[verse]
'GET /accounts/link:#account-id[\{account-id\}]/starred.changes'
Gets the changes starred by the identified user account. This
URL endpoint is functionally identical to the changes query
`GET /changes/?q=is:starred`. The result is a list of
link:rest-api-changes.html#change-info[ChangeInfo] entities.
.Request
----
GET /a/accounts/self/starred.changes
----
.Response
----
HTTP/1.1 200 OK
Content-Disposition: attachment
Content-Type: application/json;charset=UTF-8
)]}'
[
{
"kind": "gerritcodereview#change",
"id": "myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940",
"project": "myProject",
"branch": "master",
"change_id": "I8473b95934b5732ac55d26311a706c9c2bde9940",
"subject": "Implementing Feature X",
"status": "NEW",
"created": "2013-02-01 09:59:32.126000000",
"updated": "2013-02-21 11:16:36.775000000",
"mergeable": true,
"_sortkey": "0023412400000f7d",
"_number": 3965,
"owner": {
"name": "John Doe"
}
}
]
----
Star Change
~~~~~~~~~~~
[verse]
'PUT /accounts/link:#account-id[\{account-id\}]/starred.changes/link:rest-api-changes.html#change-id[\{change-id\}]'
Star a change. Starred changes are returned for the search query
`is:starred` or `starredby:USER` and automatically notify the user
whenever updates are made to the change.
.Request
----
PUT /a/accounts/self/starred.changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940 HTTP/1.0
----
.Response
----
HTTP/1.1 204 No Content
----
Unstar Change
~~~~~~~~~~~~~
[verse]
'DELETE /accounts/link:#account-id[\{account-id\}]/starred.changes/link:rest-api-changes#change-id[\{change-id\}]'
Unstar a change. Removes the starred flag, stopping notifications.
.Request
----
DELETE /a/accounts/self/starred.changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940 HTTP/1.0
----
.Response
----
HTTP/1.1 204 No Content
----
[[ids]]
IDs

View File

@ -2,7 +2,11 @@ include_defs('//gerrit-acceptance-tests/tests.defs')
acceptance_tests(
srcs = glob(['*IT.java']),
deps = [':util'],
deps = [
':util',
'//gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git:util',
'//gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change:util',
],
)
java_library(

View File

@ -0,0 +1,122 @@
// Copyright (C) 2013 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.acceptance.rest.account;
import static com.google.gerrit.acceptance.git.GitUtil.cloneProject;
import static com.google.gerrit.acceptance.git.GitUtil.createProject;
import static com.google.gerrit.acceptance.git.GitUtil.initSsh;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.AccountCreator;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.RestSession;
import com.google.gerrit.acceptance.SshSession;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.git.PushOneCommit;
import com.google.gerrit.acceptance.git.PushOneCommit.Result;
import com.google.gerrit.acceptance.rest.change.ChangeInfo;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
public class StarredChangesIT extends AbstractDaemonTest {
@Inject
private AccountCreator accounts;
@Inject
private SchemaFactory<ReviewDb> reviewDbProvider;
private TestAccount admin;
private RestSession session;
private Git git;
private ReviewDb db;
@Before
public void setUp() throws Exception {
admin = accounts.admin();
session = new RestSession(server, admin);
initSsh(admin);
Project.NameKey project = new Project.NameKey("p");
SshSession sshSession = new SshSession(server, admin);
createProject(sshSession, project.get());
git = cloneProject(sshSession.getUrl() + "/" + project.get());
sshSession.close();
db = reviewDbProvider.open();
}
@After
public void cleanup() {
db.close();
}
@Test
public void starredChangeState() throws GitAPIException, IOException,
OrmException {
Result c1 = createChange();
Result c2 = createChange();
assertNull(getChange(c1.getChangeId()).starred);
assertNull(getChange(c2.getChangeId()).starred);
starChange(true, c1.getPatchSetId().getParentKey());
starChange(true, c2.getPatchSetId().getParentKey());
assertTrue(getChange(c1.getChangeId()).starred);
assertTrue(getChange(c2.getChangeId()).starred);
starChange(false, c1.getPatchSetId().getParentKey());
starChange(false, c2.getPatchSetId().getParentKey());
assertNull(getChange(c1.getChangeId()).starred);
assertNull(getChange(c2.getChangeId()).starred);
}
private ChangeInfo getChange(String changeId) throws IOException {
RestResponse r = session.get("/changes/?q=" + changeId);
List<ChangeInfo> c = (new Gson()).fromJson(r.getReader(),
new TypeToken<List<ChangeInfo>>() {}.getType());
return c.get(0);
}
private void starChange(boolean on, Change.Id id) throws IOException {
String url = "/accounts/self/starred.changes/" + id.get();
if (on) {
RestResponse r = session.put(url);
assertEquals(204, r.getStatusCode());
} else {
RestResponse r = session.delete(url);
assertEquals(204, r.getStatusCode());
}
}
private Result createChange() throws GitAPIException, IOException {
PushOneCommit push = new PushOneCommit(db, admin.getIdent());
return push.to(git, "refs/for/master");
}
}

View File

@ -38,4 +38,5 @@ java_library(
'//lib:guava',
'//gerrit-reviewdb:server',
],
visibility = ['//gerrit-acceptance-tests/...'],
)

View File

@ -24,4 +24,5 @@ public class ChangeInfo {
String branch;
List<ChangeMessageInfo> messages;
Change.Status status;
public Boolean starred;
}

View File

@ -1,35 +0,0 @@
// Copyright (C) 2008 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.common.data;
import com.google.gerrit.common.audit.Audit;
import com.google.gerrit.common.auth.SignInRequired;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtjsonrpc.common.RemoteJsonService;
import com.google.gwtjsonrpc.common.RpcImpl;
import com.google.gwtjsonrpc.common.VoidResult;
import com.google.gwtjsonrpc.common.RpcImpl.Version;
@RpcImpl(version = Version.V2_0)
public interface ChangeListService extends RemoteJsonService {
/**
* Add and/or remove changes from the set of starred changes of the caller.
*
* @param req the add and remove cluster.
*/
@Audit
@SignInRequired
void toggleStars(ToggleStarRequest req, AsyncCallback<VoidResult> callback);
}

View File

@ -15,19 +15,23 @@
package com.google.gerrit.client.changes;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.common.data.ToggleStarRequest;
import com.google.gerrit.client.account.AccountApi;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Image;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import com.google.gwtjsonrpc.common.VoidResult;
import com.google.web.bindery.event.shared.Event;
import com.google.web.bindery.event.shared.HandlerRegistration;
import java.util.LinkedHashMap;
import java.util.Map;
/** Supports the star icon displayed on changes and tracking the status. */
public class StarredChanges {
private static final Event.Type<ChangeStarHandler> TYPE =
@ -105,57 +109,52 @@ public class StarredChanges {
public static void toggleStar(
final Change.Id changeId,
final boolean newValue) {
if (next == null) {
next = new ToggleStarRequest();
}
next.toggle(changeId, newValue);
pending.put(changeId, newValue);
fireChangeStarEvent(changeId, newValue);
if (!busy) {
start();
startRequest();
}
}
private static ToggleStarRequest next;
private static boolean busy;
private static final Map<Change.Id, Boolean> pending =
new LinkedHashMap<Change.Id, Boolean>(4);
private static void start() {
final ToggleStarRequest req = next;
next = null;
private static void startRequest() {
busy = true;
Util.LIST_SVC.toggleStars(req, new GerritCallback<VoidResult>() {
final Change.Id id = pending.keySet().iterator().next();
final boolean starred = pending.remove(id);
RestApi call = AccountApi.self().view("starred.changes").id(id.get());
AsyncCallback<JavaScriptObject> cb = new AsyncCallback<JavaScriptObject>() {
@Override
public void onSuccess(VoidResult result) {
if (next != null) {
start();
} else {
public void onSuccess(JavaScriptObject none) {
if (pending.isEmpty()) {
busy = false;
} else {
startRequest();
}
}
@Override
public void onFailure(Throwable caught) {
rollback(req);
if (next != null) {
rollback(next);
next = null;
if (!starred && RestApi.isStatus(caught, 404)) {
onSuccess(null);
return;
}
busy = false;
super.onFailure(caught);
}
});
}
private static void rollback(ToggleStarRequest req) {
if (req.getAddSet() != null) {
for (Change.Id id : req.getAddSet()) {
fireChangeStarEvent(id, false);
}
}
if (req.getRemoveSet() != null) {
for (Change.Id id : req.getRemoveSet()) {
fireChangeStarEvent(id, true);
fireChangeStarEvent(id, !starred);
for (Map.Entry<Change.Id, Boolean> e : pending.entrySet()) {
fireChangeStarEvent(e.getKey(), !e.getValue());
}
pending.clear();
busy = false;
}
};
if (starred) {
call.put(cb);
} else {
call.delete(cb);
}
}

View File

@ -15,7 +15,6 @@
package com.google.gerrit.client.changes;
import com.google.gerrit.common.data.ChangeDetailService;
import com.google.gerrit.common.data.ChangeListService;
import com.google.gerrit.common.data.ChangeManageService;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gwt.core.client.GWT;
@ -27,7 +26,6 @@ public class Util {
public static final ChangeResources R = GWT.create(ChangeResources.class);
public static final ChangeDetailService DETAIL_SVC;
public static final ChangeListService LIST_SVC;
public static final ChangeManageService MANAGE_SVC;
private static final int SUBJECT_MAX_LENGTH = 80;
@ -38,9 +36,6 @@ public class Util {
DETAIL_SVC = GWT.create(ChangeDetailService.class);
JsonUtil.bind(DETAIL_SVC, "rpc/ChangeDetailService");
LIST_SVC = GWT.create(ChangeListService.class);
JsonUtil.bind(LIST_SVC, "rpc/ChangeListService");
MANAGE_SVC = GWT.create(ChangeManageService.class);
JsonUtil.bind(MANAGE_SVC, "rpc/ChangeManageService");
}

View File

@ -1,74 +0,0 @@
// Copyright (C) 2008 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.httpd.rpc;
import com.google.gerrit.common.data.ChangeListService;
import com.google.gerrit.common.data.ToggleStarRequest;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.StarredChange;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtjsonrpc.common.VoidResult;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class ChangeListServiceImpl extends BaseServiceImplementation implements
ChangeListService {
private final Provider<CurrentUser> currentUser;
@Inject
ChangeListServiceImpl(final Provider<ReviewDb> schema,
final Provider<CurrentUser> currentUser) {
super(schema, currentUser);
this.currentUser = currentUser;
}
public void toggleStars(final ToggleStarRequest req,
final AsyncCallback<VoidResult> callback) {
run(callback, new Action<VoidResult>() {
public VoidResult run(final ReviewDb db) throws OrmException {
final Account.Id me = getAccountId();
final Set<Change.Id> existing = currentUser.get().getStarredChanges();
List<StarredChange> add = new ArrayList<StarredChange>();
List<StarredChange.Key> remove = new ArrayList<StarredChange.Key>();
if (req.getAddSet() != null) {
for (final Change.Id id : req.getAddSet()) {
if (!existing.contains(id)) {
add.add(new StarredChange(new StarredChange.Key(me, id)));
}
}
}
if (req.getRemoveSet() != null) {
for (final Change.Id id : req.getRemoveSet()) {
remove.add(new StarredChange.Key(me, id));
}
}
db.starredChanges().insert(add);
db.starredChanges().deleteKeys(remove);
return VoidResult.INSTANCE;
}
});
}
}

View File

@ -27,7 +27,6 @@ public class UiRpcModule extends RpcServletModule {
@Override
protected void configureServlets() {
rpc(ChangeListServiceImpl.class);
rpc(SuggestServiceImpl.class);
rpc(SystemInfoServiceImpl.class);

View File

@ -17,7 +17,9 @@ package com.google.gerrit.server.account;
import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.reviewdb.client.AccountSshKey;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.change.ChangeResource;
import com.google.inject.TypeLiteral;
public class AccountResource implements RestResource {
@ -33,6 +35,9 @@ public class AccountResource implements RestResource {
public static final TypeLiteral<RestView<SshKey>> SSH_KEY_KIND =
new TypeLiteral<RestView<SshKey>>() {};
public static final TypeLiteral<RestView<StarredChange>> STARRED_CHANGE_KIND =
new TypeLiteral<RestView<StarredChange>>() {};
private final IdentifiedUser user;
public AccountResource(IdentifiedUser user) {
@ -90,4 +95,17 @@ public class AccountResource implements RestResource {
return sshKey;
}
}
public static class StarredChange extends AccountResource {
private final ChangeResource change;
public StarredChange(IdentifiedUser user, ChangeResource change) {
super(user);
this.change = change;
}
public Change getChange() {
return change.getChange();
}
}
}

View File

@ -18,6 +18,7 @@ import static com.google.gerrit.server.account.AccountResource.ACCOUNT_KIND;
import static com.google.gerrit.server.account.AccountResource.CAPABILITY_KIND;
import static com.google.gerrit.server.account.AccountResource.EMAIL_KIND;
import static com.google.gerrit.server.account.AccountResource.SSH_KEY_KIND;
import static com.google.gerrit.server.account.AccountResource.STARRED_CHANGE_KIND;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.RestApiModule;
@ -30,9 +31,10 @@ public class Module extends RestApiModule {
bind(Capabilities.class);
DynamicMap.mapOf(binder(), ACCOUNT_KIND);
DynamicMap.mapOf(binder(), CAPABILITY_KIND);
DynamicMap.mapOf(binder(), EMAIL_KIND);
DynamicMap.mapOf(binder(), SSH_KEY_KIND);
DynamicMap.mapOf(binder(), CAPABILITY_KIND);
DynamicMap.mapOf(binder(), STARRED_CHANGE_KIND);
put(ACCOUNT_KIND).to(PutAccount.class);
get(ACCOUNT_KIND).to(GetAccount.class);
@ -65,6 +67,11 @@ public class Module extends RestApiModule {
put(ACCOUNT_KIND, "preferences.diff").to(SetDiffPreferences.class);
get(CAPABILITY_KIND).to(GetCapabilities.CheckOne.class);
child(ACCOUNT_KIND, "starred.changes").to(StarredChanges.class);
put(STARRED_CHANGE_KIND).to(StarredChanges.Put.class);
delete(STARRED_CHANGE_KIND).to(StarredChanges.Delete.class);
bind(StarredChanges.Create.class);
install(new FactoryModuleBuilder().build(CreateAccount.Factory.class));
install(new FactoryModuleBuilder().build(CreateEmail.Factory.class));
}

View File

@ -0,0 +1,199 @@
// Copyright (C) 2013 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.account;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.AcceptsCreate;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ChildCollection;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.reviewdb.client.StarredChange;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.ChangesCollection;
import com.google.gerrit.server.query.change.QueryChanges;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
class StarredChanges implements
ChildCollection<AccountResource, AccountResource.StarredChange>,
AcceptsCreate<AccountResource> {
private static final Logger log = LoggerFactory.getLogger(StarredChanges.class);
private final ChangesCollection changes;
private final DynamicMap<RestView<AccountResource.StarredChange>> views;
private final Provider<Create> createProvider;
@Inject
StarredChanges(ChangesCollection changes,
DynamicMap<RestView<AccountResource.StarredChange>> views,
Provider<Create> createProvider) {
this.changes = changes;
this.views = views;
this.createProvider = createProvider;
}
@Override
public AccountResource.StarredChange parse(AccountResource parent, IdString id)
throws ResourceNotFoundException, OrmException, UnsupportedEncodingException {
IdentifiedUser user = parent.getUser();
try {
user.asyncStarredChanges();
ChangeResource change = changes.parse(TopLevelResource.INSTANCE, id);
if (user.getStarredChanges().contains(change.getChange().getId())) {
return new AccountResource.StarredChange(user, change);
}
throw new ResourceNotFoundException(id);
} finally {
user.abortStarredChanges();
}
}
@Override
public DynamicMap<RestView<AccountResource.StarredChange>> views() {
return views;
}
@Override
public RestView<AccountResource> list() throws ResourceNotFoundException {
return new RestReadView<AccountResource>() {
@Override
public Object apply(AccountResource self) throws BadRequestException,
AuthException, OrmException {
QueryChanges query = changes.list();
query.addQuery("starredby:" + self.getUser().getAccountId().get());
return query.apply(TopLevelResource.INSTANCE);
}
};
}
@SuppressWarnings("unchecked")
@Override
public RestModifyView<AccountResource, EmptyInput> create(
AccountResource parent, IdString id) throws UnprocessableEntityException{
try {
return createProvider.get()
.setChange(changes.parse(TopLevelResource.INSTANCE, id));
} catch (ResourceNotFoundException e) {
throw new UnprocessableEntityException(String.format("change %s not found", id.get()));
} catch (UnsupportedEncodingException e) {
log.error("cannot resolve change", e);
throw new UnprocessableEntityException("internal server error");
} catch (OrmException e) {
log.error("cannot resolve change", e);
throw new UnprocessableEntityException("internal server error");
}
}
static class Create implements RestModifyView<AccountResource, EmptyInput> {
private final Provider<CurrentUser> self;
private final Provider<ReviewDb> dbProvider;
private ChangeResource change;
@Inject
Create(Provider<CurrentUser> self, Provider<ReviewDb> dbProvider) {
this.self = self;
this.dbProvider = dbProvider;
}
Create setChange(ChangeResource change) {
this.change = change;
return this;
}
@Override
public Response<?> apply(AccountResource rsrc, EmptyInput in)
throws AuthException, OrmException {
if (self.get() != rsrc.getUser()) {
throw new AuthException("not allowed to add starred change");
}
try {
dbProvider.get().starredChanges().insert(Collections.singleton(
new StarredChange(new StarredChange.Key(
rsrc.getUser().getAccountId(),
change.getChange().getId()))));
} catch (OrmDuplicateKeyException e) {
return Response.none();
}
return Response.none();
}
}
static class Put implements
RestModifyView<AccountResource.StarredChange, EmptyInput> {
private final Provider<CurrentUser> self;
@Inject
Put(Provider<CurrentUser> self) {
this.self = self;
}
@Override
public Response<?> apply(AccountResource.StarredChange rsrc, EmptyInput in)
throws AuthException, OrmException {
if (self.get() != rsrc.getUser()) {
throw new AuthException("not allowed update starred changes");
}
return Response.none();
}
}
static class Delete implements
RestModifyView<AccountResource.StarredChange, EmptyInput> {
private final Provider<CurrentUser> self;
private final Provider<ReviewDb> dbProvider;
@Inject
Delete(Provider<CurrentUser> self, Provider<ReviewDb> dbProvider) {
this.self = self;
this.dbProvider = dbProvider;
}
@Override
public Response<?> apply(AccountResource.StarredChange rsrc,
EmptyInput in) throws AuthException, OrmException {
if (self.get() != rsrc.getUser()) {
throw new AuthException("not allowed remove starred change");
}
dbProvider.get().starredChanges().delete(Collections.singleton(
new StarredChange(new StarredChange.Key(
rsrc.getUser().getAccountId(),
rsrc.getChange().getId()))));
return Response.none();
}
}
static class EmptyInput {
}
}

View File

@ -58,7 +58,7 @@ public class ChangesCollection implements
}
@Override
public RestView<TopLevelResource> list() {
public QueryChanges list() {
return queryFactory.get();
}