From 732d2b7b3c65fbf7e346ff3955ee130de5429a02 Mon Sep 17 00:00:00 2001 From: David Ostrovsky Date: Mon, 28 Apr 2014 00:26:30 +0200 Subject: [PATCH] Implement extension-api for accounts Change-Id: I689f3e17deaa1319e3b731a78efcb83bb97999f9 --- .../acceptance/api/accounts/AccountIT.java | 69 ++++++++++++++ .../gerrit/acceptance/api/accounts/BUCK | 6 ++ .../gerrit/server/account/StarredChanges.java | 10 +- .../gerrit/server/api/GerritApiImpl.java | 11 ++- .../com/google/gerrit/server/api/Module.java | 1 + .../server/api/accounts/AccountApiImpl.java | 93 +++++++++++++++++++ .../api/accounts/AccountInfoMapper.java | 37 ++++++++ .../server/api/accounts/AccountsImpl.java | 62 +++++++++++++ .../gerrit/server/api/accounts/Module.java | 27 ++++++ .../server/api/changes/ChangeInfoMapper.java | 34 ++----- 10 files changed, 318 insertions(+), 32 deletions(-) create mode 100644 gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java create mode 100644 gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/BUCK create mode 100644 gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java create mode 100644 gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountInfoMapper.java create mode 100644 gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java create mode 100644 gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/Module.java diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java new file mode 100644 index 0000000000..c95f8c3b34 --- /dev/null +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java @@ -0,0 +1,69 @@ +// Copyright (C) 2014 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.api.accounts; + +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.PushOneCommit; +import com.google.gerrit.extensions.common.AccountInfo; +import com.google.gerrit.extensions.restapi.RestApiException; + +import org.eclipse.jgit.api.errors.GitAPIException; +import org.junit.Test; + +import java.io.IOException; + +public class AccountIT extends AbstractDaemonTest { + + @Test + public void get() throws RestApiException { + AccountInfo info = gApi + .accounts() + .id("admin") + .get(); + assertEquals("Administrator", info.name); + assertEquals("admin@example.com", info.email); + assertEquals("admin", info.username); + } + + @Test + public void self() throws RestApiException { + AccountInfo info = gApi + .accounts() + .self() + .get(); + assertEquals("Administrator", info.name); + assertEquals("admin@example.com", info.email); + assertEquals("admin", info.username); + } + + @Test + public void starUnstarChange() throws GitAPIException, + IOException, RestApiException { + PushOneCommit.Result r = createChange(); + String triplet = "p~master~" + r.getChangeId(); + gApi.accounts() + .self() + .starChange(triplet); + assertTrue(getChange(triplet).starred); + gApi.accounts() + .self() + .unstarChange(triplet); + assertNull(getChange(triplet).starred); + } +} diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/BUCK b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/BUCK new file mode 100644 index 0000000000..1152d88d26 --- /dev/null +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/BUCK @@ -0,0 +1,6 @@ +include_defs('//gerrit-acceptance-tests/tests.defs') + +acceptance_tests( + srcs = glob(['*IT.java']), + labels = ['api'], +) diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/StarredChanges.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/StarredChanges.java index b8984ab2fa..43f7211579 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/StarredChanges.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/StarredChanges.java @@ -44,7 +44,7 @@ import org.slf4j.LoggerFactory; import java.util.Collections; -class StarredChanges implements +public class StarredChanges implements ChildCollection, AcceptsCreate { private static final Logger log = LoggerFactory.getLogger(StarredChanges.class); @@ -112,7 +112,7 @@ class StarredChanges implements } } - static class Create implements RestModifyView { + public static class Create implements RestModifyView { private final Provider self; private final Provider dbProvider; private ChangeResource change; @@ -123,7 +123,7 @@ class StarredChanges implements this.dbProvider = dbProvider; } - Create setChange(ChangeResource change) { + public Create setChange(ChangeResource change) { this.change = change; return this; } @@ -165,7 +165,7 @@ class StarredChanges implements } } - static class Delete implements + public static class Delete implements RestModifyView { private final Provider self; private final Provider dbProvider; @@ -190,6 +190,6 @@ class StarredChanges implements } } - static class EmptyInput { + public static class EmptyInput { } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/GerritApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/GerritApiImpl.java index f7ca136d81..6815bb1dde 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/api/GerritApiImpl.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/GerritApiImpl.java @@ -14,6 +14,7 @@ package com.google.gerrit.server.api; +import com.google.gerrit.extensions.api.accounts.Accounts; import com.google.gerrit.extensions.api.GerritApi; import com.google.gerrit.extensions.api.changes.Changes; import com.google.gerrit.extensions.api.projects.Projects; @@ -21,16 +22,24 @@ import com.google.inject.Inject; import com.google.inject.Provider; class GerritApiImpl extends GerritApi.NotImplemented implements GerritApi { + private final Provider accounts; private final Provider changes; private final Provider projects; @Inject - GerritApiImpl(Provider changes, + GerritApiImpl(Provider accounts, + Provider changes, Provider projects) { + this.accounts = accounts; this.changes = changes; this.projects = projects; } + @Override + public Accounts accounts() { + return accounts.get(); + } + @Override public Changes changes() { return changes.get(); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/Module.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/Module.java index 1919ff5068..23f4b8dfe7 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/api/Module.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/Module.java @@ -24,5 +24,6 @@ public class Module extends AbstractModule { install(new com.google.gerrit.server.api.changes.Module()); install(new com.google.gerrit.server.api.projects.Module()); + install(new com.google.gerrit.server.api.accounts.Module()); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java new file mode 100644 index 0000000000..b1fd979b70 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java @@ -0,0 +1,93 @@ +// Copyright (C) 2014 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.api.accounts; + +import com.google.gerrit.extensions.api.accounts.AccountApi; +import com.google.gerrit.extensions.restapi.IdString; +import com.google.gerrit.extensions.restapi.RestApiException; +import com.google.gerrit.extensions.restapi.TopLevelResource; +import com.google.gerrit.server.account.AccountInfo; +import com.google.gerrit.server.account.AccountResource; +import com.google.gerrit.server.account.StarredChanges; +import com.google.gerrit.server.change.ChangeResource; +import com.google.gerrit.server.change.ChangesCollection; +import com.google.gwtorm.server.OrmException; +import com.google.inject.Inject; +import com.google.inject.assistedinject.Assisted; + +public class AccountApiImpl extends AccountApi.NotImplemented implements AccountApi { + interface Factory { + AccountApiImpl create(AccountResource account); + } + + private final AccountResource account; + private final ChangesCollection changes; + private final AccountInfo.Loader.Factory accountLoaderFactory; + private final StarredChanges.Create starredChangesCreate; + private final StarredChanges.Delete starredChangesDelete; + + @Inject + AccountApiImpl(AccountInfo.Loader.Factory ailf, + ChangesCollection changes, + StarredChanges.Create starredChangesCreate, + StarredChanges.Delete starredChangesDelete, + @Assisted AccountResource account) { + this.account = account; + this.accountLoaderFactory = ailf; + this.changes = changes; + this.starredChangesCreate = starredChangesCreate; + this.starredChangesDelete = starredChangesDelete; + } + + @Override + public com.google.gerrit.extensions.common.AccountInfo get() + throws RestApiException { + AccountInfo.Loader accountLoader = accountLoaderFactory.create(true); + try { + AccountInfo ai = accountLoader.get(account.getUser().getAccountId()); + accountLoader.fill(); + return AccountInfoMapper.fromAcountInfo(ai); + } catch (OrmException e) { + throw new RestApiException("Cannot parse change", e); + } + } + + @Override + public void starChange(String id) throws RestApiException { + try { + ChangeResource rsrc = changes.parse( + TopLevelResource.INSTANCE, + IdString.fromUrl(id)); + starredChangesCreate.setChange(rsrc); + starredChangesCreate.apply(account, new StarredChanges.EmptyInput()); + } catch (OrmException e) { + throw new RestApiException("Cannot star change", e); + } + } + + @Override + public void unstarChange(String id) throws RestApiException { + try { + ChangeResource rsrc = + changes.parse(TopLevelResource.INSTANCE, IdString.fromUrl(id)); + AccountResource.StarredChange starredChange = + new AccountResource.StarredChange(account.getUser(), rsrc); + starredChangesDelete.apply(starredChange, + new StarredChanges.EmptyInput()); + } catch (OrmException e) { + throw new RestApiException("Cannot unstar change", e); + } + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountInfoMapper.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountInfoMapper.java new file mode 100644 index 0000000000..10a9116ead --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountInfoMapper.java @@ -0,0 +1,37 @@ +// Copyright (C) 2014 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.api.accounts; + +import com.google.gerrit.extensions.common.AccountInfo; + +public class AccountInfoMapper { + public static AccountInfo fromAcountInfo( + com.google.gerrit.server.account.AccountInfo i) { + if (i == null) { + return null; + } + AccountInfo ai = new AccountInfo(); + fromAccount(i, ai); + return ai; + } + + public static void fromAccount( + com.google.gerrit.server.account.AccountInfo i, AccountInfo ai) { + ai._accountId = i._accountId; + ai.email = i.email; + ai.name = i.name; + ai.username = i.username; + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java new file mode 100644 index 0000000000..3f0ecfbda0 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java @@ -0,0 +1,62 @@ +// Copyright (C) 2014 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.api.accounts; + +import com.google.gerrit.extensions.api.accounts.AccountApi; +import com.google.gerrit.extensions.api.accounts.Accounts; +import com.google.gerrit.extensions.restapi.AuthException; +import com.google.gerrit.extensions.restapi.IdString; +import com.google.gerrit.extensions.restapi.RestApiException; +import com.google.gerrit.extensions.restapi.TopLevelResource; +import com.google.gerrit.server.CurrentUser; +import com.google.gerrit.server.IdentifiedUser; +import com.google.gerrit.server.account.AccountResource; +import com.google.gerrit.server.account.AccountsCollection; +import com.google.gwtorm.server.OrmException; +import com.google.inject.Inject; +import com.google.inject.Provider; + +public class AccountsImpl extends Accounts.NotImplemented implements Accounts { + private final AccountsCollection accounts; + private final AccountApiImpl.Factory api; + private final Provider self; + + @Inject + AccountsImpl(AccountsCollection accounts, + AccountApiImpl.Factory api, + Provider self) { + this.accounts = accounts; + this.api = api; + this.self = self; + } + + @Override + public AccountApi id(String id) throws RestApiException { + try { + return api.create(accounts.parse(TopLevelResource.INSTANCE, + IdString.fromDecoded(id))); + } catch (OrmException e) { + throw new RestApiException("Cannot parse change", e); + } + } + + @Override + public AccountApi self() throws RestApiException { + if (!self.get().isIdentifiedUser()) { + throw new AuthException("Authentication required"); + } + return api.create(new AccountResource((IdentifiedUser)self.get())); + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/Module.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/Module.java new file mode 100644 index 0000000000..5e3855e1c2 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/Module.java @@ -0,0 +1,27 @@ +// Copyright (C) 2014 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.api.accounts; + +import com.google.gerrit.extensions.api.accounts.Accounts; +import com.google.gerrit.server.config.FactoryModule; + +public class Module extends FactoryModule { + @Override + protected void configure() { + bind(Accounts.class).to(AccountsImpl.class); + + factory(AccountApiImpl.Factory.class); + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeInfoMapper.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeInfoMapper.java index 444676fdb2..c2dae0dba4 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeInfoMapper.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeInfoMapper.java @@ -24,7 +24,6 @@ import static com.google.gerrit.extensions.common.ListChangesOption.MESSAGES; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.gerrit.extensions.common.AccountInfo; import com.google.gerrit.extensions.common.ApprovalInfo; import com.google.gerrit.extensions.common.ChangeInfo; import com.google.gerrit.extensions.common.ChangeMessageInfo; @@ -33,6 +32,7 @@ import com.google.gerrit.extensions.common.LabelInfo; import com.google.gerrit.extensions.common.ListChangesOption; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change.Status; +import com.google.gerrit.server.api.accounts.AccountInfoMapper; import com.google.gerrit.server.change.ChangeJson; import java.util.EnumSet; @@ -87,7 +87,7 @@ class ChangeInfoMapper { o.mergeable = i.mergeable; o.insertions = i.insertions; o.deletions = i.deletions; - o.owner = fromAcountInfo(i.owner); + o.owner = AccountInfoMapper.fromAcountInfo(i.owner); o.currentRevision = i.currentRevision; o._number = i._number; } @@ -98,7 +98,7 @@ class ChangeInfoMapper { for (ChangeJson.ChangeMessageInfo m : i.messages) { ChangeMessageInfo cmi = new ChangeMessageInfo(); cmi.id = m.id; - cmi.author = fromAcountInfo(m.author); + cmi.author = AccountInfoMapper.fromAcountInfo(m.author); cmi.date = m.date; cmi.message = m.message; cmi._revisionNumber = m._revisionNumber; @@ -112,10 +112,10 @@ class ChangeInfoMapper { for (Map.Entry e : i.labels.entrySet()) { ChangeJson.LabelInfo li = e.getValue(); LabelInfo lo = new LabelInfo(); - lo.approved = fromAcountInfo(li.approved); - lo.rejected = fromAcountInfo(li.rejected); - lo.recommended = fromAcountInfo(li.recommended); - lo.disliked = fromAcountInfo(li.disliked); + lo.approved = AccountInfoMapper.fromAcountInfo(li.approved); + lo.rejected = AccountInfoMapper.fromAcountInfo(li.rejected); + lo.recommended = AccountInfoMapper.fromAcountInfo(li.recommended); + lo.disliked = AccountInfoMapper.fromAcountInfo(li.disliked); lo.value = li.value; lo.defaultValue = li.defaultValue; lo.optional = li.optional; @@ -140,25 +140,7 @@ class ChangeInfoMapper { ApprovalInfo ao = new ApprovalInfo(); ao.value = ai.value; ao.date = ai.date; - fromAccount(ai, ao); + AccountInfoMapper.fromAccount(ai, ao); return ao; } - - private static AccountInfo fromAcountInfo( - com.google.gerrit.server.account.AccountInfo i) { - if (i == null) { - return null; - } - AccountInfo ai = new AccountInfo(); - fromAccount(i, ai); - return ai; - } - - private static void fromAccount( - com.google.gerrit.server.account.AccountInfo i, AccountInfo ai) { - ai._accountId = i._accountId; - ai.email = i.email; - ai.name = i.name; - ai.username = i.username; - } }