GetServerInfo: Include configured contributor agreements

When contributor agreements are enabled, include the list of configured
contributor agreements in the `auth` section.

Add support to get the server info via the API, and use this in the
existing agreements acceptance test to verify that the agreements are
returned as expected.

Change-Id: Ie6c8d25a4cd1519e3a42eb4cb3e6aeea77e56651
diff --git a/Documentation/rest-api-config.txt b/Documentation/rest-api-config.txt
index a378462..5d08613 100644
--- a/Documentation/rest-api-config.txt
+++ b/Documentation/rest-api-config.txt
@@ -54,6 +54,14 @@
   {
     "auth": {
       "auth_type": "LDAP",
+      "use_contributor_agreements": true,
+      "contributor_agreements": [
+        {
+          "name": "Individual",
+          "description": "If you are going to be contributing code on your own, this is the one you want. You can sign this one online.",
+          "url": "static/cla_individual.html"
+        }
+      ],
       "editable_account_fields": [
         "FULL_NAME",
         "REGISTER_NEW_EMAIL"
@@ -1226,6 +1234,9 @@
 |`use_contributor_agreements` |not set if `false`|
 Whether link:config-gerrit.html#auth.contributorAgreements[contributor
 agreements] are required.
+|`contributor_agreements`     |not set if `use_contributor_agreements` is `false`|
+List of contributor agreements as link:rest-api-accounts.html#contributor-agreement-info[
+ContributorAgreementInfo] entities.
 |`editable_account_fields`    ||
 List of account fields that are editable. Possible values are
 `FULL_NAME`, `USER_NAME` and `REGISTER_NEW_EMAIL`.
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
index 2cbcca8..e6049d5 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
@@ -24,6 +24,7 @@
 import com.google.gerrit.common.data.PermissionRule;
 import com.google.gerrit.extensions.api.groups.GroupApi;
 import com.google.gerrit.extensions.common.AgreementInfo;
+import com.google.gerrit.extensions.common.ServerInfo;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
@@ -76,6 +77,25 @@
   }
 
   @Test
+  public void getAvailableAgreements() throws Exception {
+    ServerInfo info = gApi.config().server().getInfo();
+    if (isContributorAgreementsEnabled()) {
+      assertThat(info.auth.useContributorAgreements).isTrue();
+      assertThat(info.auth.contributorAgreements).hasSize(2);
+      AgreementInfo agreementInfo = info.auth.contributorAgreements.get(0);
+      assertThat(agreementInfo.name).isEqualTo(ca.getName());
+      assertThat(agreementInfo.autoVerifyGroup.name)
+          .isEqualTo(ca.getAutoVerify().getName());
+      agreementInfo = info.auth.contributorAgreements.get(1);
+      assertThat(agreementInfo.name).isEqualTo(ca2.getName());
+      assertThat(agreementInfo.autoVerifyGroup).isNull();
+    } else {
+      assertThat(info.auth.useContributorAgreements).isNull();
+      assertThat(info.auth.contributorAgreements).isNull();
+    }
+  }
+
+  @Test
   public void signNonExistingAgreement() throws Exception {
     assume().that(isContributorAgreementsEnabled()).isTrue();
     exception.expect(UnprocessableEntityException.class);
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/config/Server.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/config/Server.java
index a43c29f..1e5c95e 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/config/Server.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/config/Server.java
@@ -16,6 +16,7 @@
 
 import com.google.gerrit.extensions.client.DiffPreferencesInfo;
 import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
+import com.google.gerrit.extensions.common.ServerInfo;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 
@@ -25,6 +26,8 @@
    */
   String getVersion() throws RestApiException;
 
+  ServerInfo getInfo() throws RestApiException;
+
   GeneralPreferencesInfo getDefaultPreferences() throws RestApiException;
   GeneralPreferencesInfo setDefaultPreferences(GeneralPreferencesInfo in)
       throws RestApiException;
@@ -43,6 +46,11 @@
     }
 
     @Override
+    public ServerInfo getInfo() throws RestApiException {
+      throw new NotImplementedException();
+    }
+
+    @Override
     public GeneralPreferencesInfo getDefaultPreferences()
         throws RestApiException {
       throw new NotImplementedException();
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/AuthInfo.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/AuthInfo.java
index c7adba3..1000e9c 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/AuthInfo.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/AuthInfo.java
@@ -22,6 +22,7 @@
 public class AuthInfo {
   public AuthType authType;
   public Boolean useContributorAgreements;
+  public List<AgreementInfo> contributorAgreements;
   public List<AccountFieldName> editableAccountFields;
   public String loginUrl;
   public String loginText;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/config/ServerImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/config/ServerImpl.java
index 8339ecf..f433d2b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/config/ServerImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/config/ServerImpl.java
@@ -18,10 +18,12 @@
 import com.google.gerrit.extensions.api.config.Server;
 import com.google.gerrit.extensions.client.DiffPreferencesInfo;
 import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
+import com.google.gerrit.extensions.common.ServerInfo;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.config.GetDiffPreferences;
 import com.google.gerrit.server.config.GetPreferences;
+import com.google.gerrit.server.config.GetServerInfo;
 import com.google.gerrit.server.config.SetDiffPreferences;
 import com.google.gerrit.server.config.SetPreferences;
 import com.google.inject.Inject;
@@ -37,16 +39,19 @@
   private final SetPreferences setPreferences;
   private final GetDiffPreferences getDiffPreferences;
   private final SetDiffPreferences setDiffPreferences;
+  private final GetServerInfo getServerInfo;
 
   @Inject
   ServerImpl(GetPreferences getPreferences,
       SetPreferences setPreferences,
       GetDiffPreferences getDiffPreferences,
-      SetDiffPreferences setDiffPreferences) {
+      SetDiffPreferences setDiffPreferences,
+      GetServerInfo getServerInfo) {
     this.getPreferences = getPreferences;
     this.setPreferences = setPreferences;
     this.getDiffPreferences = getDiffPreferences;
     this.setDiffPreferences = setDiffPreferences;
+    this.getServerInfo = getServerInfo;
   }
 
   @Override
@@ -55,6 +60,15 @@
   }
 
   @Override
+  public ServerInfo getInfo() throws RestApiException {
+    try {
+      return getServerInfo.apply(new ConfigResource());
+    } catch (IOException e) {
+      throw new RestApiException("Cannot get server info", e);
+    }
+  }
+
+  @Override
   public GeneralPreferencesInfo getDefaultPreferences()
       throws RestApiException {
     try {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GetServerInfo.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GetServerInfo.java
index 0f75bb9..9e2ad77 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GetServerInfo.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GetServerInfo.java
@@ -20,6 +20,7 @@
 import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
+import com.google.gerrit.common.data.ContributorAgreement;
 import com.google.gerrit.extensions.common.AuthInfo;
 import com.google.gerrit.extensions.common.ChangeConfigInfo;
 import com.google.gerrit.extensions.common.DownloadInfo;
@@ -47,12 +48,14 @@
 import com.google.gerrit.server.change.Submit;
 import com.google.gerrit.server.documentation.QueryDocumentationExecutor;
 import com.google.gerrit.server.notedb.NotesMigration;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.inject.Inject;
 
 import org.eclipse.jgit.lib.Config;
 
 import java.net.MalformedURLException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
@@ -77,6 +80,8 @@
   private final boolean enableSignedPush;
   private final QueryDocumentationExecutor docSearcher;
   private final NotesMigration migration;
+  private final ProjectCache projectCache;
+  private final AgreementJson agreementJson;
 
   @Inject
   public GetServerInfo(
@@ -94,7 +99,9 @@
       DynamicItem<AvatarProvider> avatar,
       @EnableSignedPush boolean enableSignedPush,
       QueryDocumentationExecutor docSearcher,
-      NotesMigration migration) {
+      NotesMigration migration,
+      ProjectCache projectCache,
+      AgreementJson agreementJson) {
     this.config = config;
     this.authConfig = authConfig;
     this.realm = realm;
@@ -110,6 +117,8 @@
     this.enableSignedPush = enableSignedPush;
     this.docSearcher = docSearcher;
     this.migration = migration;
+    this.projectCache = projectCache;
+    this.agreementJson = agreementJson;
   }
 
   @Override
@@ -142,6 +151,18 @@
     info.switchAccountUrl = cfg.getSwitchAccountUrl();
     info.isGitBasicAuth = toBoolean(cfg.isGitBasicAuth());
 
+    if (info.useContributorAgreements != null) {
+      Collection<ContributorAgreement> agreements =
+          projectCache.getAllProjects().getConfig().getContributorAgreements();
+      if (!agreements.isEmpty()) {
+        info.contributorAgreements =
+            Lists.newArrayListWithCapacity(agreements.size());
+        for (ContributorAgreement agreement: agreements) {
+          info.contributorAgreements.add(agreementJson.format(agreement));
+        }
+      }
+    }
+
     switch (info.authType) {
       case LDAP:
       case LDAP_BIND: