Merge "Add REST API to toggle starred change state" into stable-2.8
This commit is contained in:
commit
f4a8de43a6
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
@ -38,4 +38,5 @@ java_library(
|
||||
'//lib:guava',
|
||||
'//gerrit-reviewdb:server',
|
||||
],
|
||||
visibility = ['//gerrit-acceptance-tests/...'],
|
||||
)
|
||||
|
@ -24,4 +24,5 @@ public class ChangeInfo {
|
||||
String branch;
|
||||
List<ChangeMessageInfo> messages;
|
||||
Change.Status status;
|
||||
public Boolean starred;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -27,7 +27,6 @@ public class UiRpcModule extends RpcServletModule {
|
||||
|
||||
@Override
|
||||
protected void configureServlets() {
|
||||
rpc(ChangeListServiceImpl.class);
|
||||
rpc(SuggestServiceImpl.class);
|
||||
rpc(SystemInfoServiceImpl.class);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
@ -58,7 +58,7 @@ public class ChangesCollection implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestView<TopLevelResource> list() {
|
||||
public QueryChanges list() {
|
||||
return queryFactory.get();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user