Merge branch 'stable-3.0'

* stable-3.0:
  Upgrade bazlets to latest stable-3.0
  Upgrade bazlets to latest stable-2.16
  Upgrade bazlets to latest stable-2.15
  Upgrade bazlets to latest stable-2.14

Change-Id: I6c8b595e65a75a3aad411b671263636edda69c38
diff --git a/WORKSPACE b/WORKSPACE
index 6c8bde4..5ace8a3 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,7 +3,7 @@
 load("//:bazlets.bzl", "load_bazlets")
 
 load_bazlets(
-    commit = "8ac9d00b8f12b7f61ff360c47a5bd87d7f75f4b5",
+    commit = "8c8df720486ebe0b60adccd0eceb1c8122edaf58",
     #local_path = "/home/<user>/projects/bazlets",
 )
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHub2Api.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHub2Api.java
index 4b8419b..338e3cc 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHub2Api.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHub2Api.java
@@ -20,16 +20,22 @@
 
 public class GitHub2Api extends DefaultApi20 {
   private static final String AUTHORIZE_URL =
-      "https://github.com/login/oauth/authorize?client_id=%s&redirect_uri=%s";
+      "%slogin/oauth/authorize?client_id=%s&redirect_uri=%s";
+
+  private final String rootUrl;
+
+  public GitHub2Api(String rootUrl) {
+    this.rootUrl = rootUrl;
+  }
 
   @Override
   public String getAccessTokenEndpoint() {
-    return "https://github.com/login/oauth/access_token";
+    return String.format("%slogin/oauth/access_token", rootUrl);
   }
 
   @Override
   public String getAuthorizationUrl(OAuthConfig config) {
     return String.format(
-        AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
+        AUTHORIZE_URL, rootUrl, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHubOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHubOAuthService.java
index 1c73c0e..79289de 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHubOAuthService.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHubOAuthService.java
@@ -47,7 +47,10 @@
   private static final Logger log = LoggerFactory.getLogger(GitHubOAuthService.class);
   static final String CONFIG_SUFFIX = "-github-oauth";
   private static final String GITHUB_PROVIDER_PREFIX = "github-oauth:";
-  private static final String PROTECTED_RESOURCE_URL = "https://api.github.com/user";
+  private static final String GITHUB_API_ENDPOINT_URL = "https://api.github.com/";
+  private static final String GHE_API_ENDPOINT_URL = "%sapi/v3/";
+  static final String GITHUB_ROOT_URL = "https://github.com/";
+  private final String rootUrl;
 
   private static final String SCOPE = "user:email";
   private final boolean fixLegacyUserId;
@@ -61,9 +64,13 @@
     PluginConfig cfg = cfgFactory.getFromGerritConfig(pluginName + CONFIG_SUFFIX);
     String canonicalWebUrl = CharMatcher.is('/').trimTrailingFrom(urlProvider.get()) + "/";
     fixLegacyUserId = cfg.getBoolean(InitOAuth.FIX_LEGACY_USER_ID, false);
+    rootUrl =
+        CharMatcher.is('/').trimTrailingFrom(cfg.getString(InitOAuth.ROOT_URL, GITHUB_ROOT_URL))
+            + "/";
+
     service =
         new ServiceBuilder()
-            .provider(GitHub2Api.class)
+            .provider(new GitHub2Api(rootUrl))
             .apiKey(cfg.getString(InitOAuth.CLIENT_ID))
             .apiSecret(cfg.getString(InitOAuth.CLIENT_SECRET))
             .callback(canonicalWebUrl + "oauth")
@@ -71,9 +78,19 @@
             .build();
   }
 
+  private String getApiUrl() {
+    return GITHUB_ROOT_URL.equals(rootUrl)
+        ? GITHUB_API_ENDPOINT_URL
+        : String.format(GHE_API_ENDPOINT_URL, rootUrl);
+  }
+
+  private String getProtectedResourceUrl() {
+    return getApiUrl() + "user";
+  }
+
   @Override
   public OAuthUserInfo getUserInfo(OAuthToken token) throws IOException {
-    OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+    OAuthRequest request = new OAuthRequest(Verb.GET, getProtectedResourceUrl());
     Token t = new Token(token.getToken(), token.getSecret(), token.getRaw());
     service.signRequest(t, request);
     Response response = request.send();
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 757ea1e..a97fd16 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -19,6 +19,7 @@
     link-to-existing-openid-accounts = true
 
   [plugin "@PLUGIN@-github-oauth"]
+    root-url = "<github url>" # https://github.com/ or https://git.company.com/
     client-id = "<client-id>"
     client-secret = "<client-secret>"
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/oauth/GithubApiUrlTest.java b/src/test/java/com/googlesource/gerrit/plugins/oauth/GithubApiUrlTest.java
new file mode 100644
index 0000000..64e4916
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/oauth/GithubApiUrlTest.java
@@ -0,0 +1,106 @@
+// Copyright (C) 2019 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.googlesource.gerrit.plugins.oauth;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Strings;
+import com.google.gerrit.extensions.auth.oauth.OAuthServiceProvider;
+import com.google.gerrit.server.config.PluginConfig;
+import com.google.gerrit.server.config.PluginConfigFactory;
+import com.google.inject.Provider;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import org.eclipse.jgit.lib.Config;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class GithubApiUrlTest {
+  private static final String PLUGIN_NAME = "gerrit-oauth-provider";
+  private static final String CANONICAL_URL = "https://localhost";
+  private static final String TEST_CLIENT_ID = "test_client_id";
+
+  @Mock private PluginConfigFactory pluginConfigFactoryMock;
+  @Mock private Provider<String> urlProviderMock;
+
+  private OAuthServiceProvider getGithubOAuthProvider(String rootUrl) {
+    PluginConfig pluginConfig =
+        new PluginConfig(PLUGIN_NAME + GitHubOAuthService.CONFIG_SUFFIX, new Config());
+    if (!Strings.isNullOrEmpty(rootUrl)) {
+      pluginConfig.setString(InitOAuth.ROOT_URL, rootUrl);
+    }
+    pluginConfig.setString(InitOAuth.CLIENT_ID, TEST_CLIENT_ID);
+    pluginConfig.setString(InitOAuth.CLIENT_SECRET, "secret");
+    when(pluginConfigFactoryMock.getFromGerritConfig(
+            PLUGIN_NAME + GitHubOAuthService.CONFIG_SUFFIX))
+        .thenReturn(pluginConfig);
+    when(urlProviderMock.get()).thenReturn(CANONICAL_URL);
+
+    return new GitHubOAuthService(pluginConfigFactoryMock, PLUGIN_NAME, urlProviderMock);
+  }
+
+  private String getExpectedUrl(String rootUrl) throws Exception {
+    if (rootUrl == null) {
+      rootUrl = GitHubOAuthService.GITHUB_ROOT_URL;
+    }
+    rootUrl = CharMatcher.is('/').trimTrailingFrom(rootUrl) + "/";
+    return String.format(
+        "%slogin/oauth/authorize?client_id=%s&redirect_uri=%s%s",
+        rootUrl,
+        TEST_CLIENT_ID,
+        URLEncoder.encode(CANONICAL_URL, StandardCharsets.UTF_8.name()),
+        URLEncoder.encode("/oauth", StandardCharsets.UTF_8.name()));
+  }
+
+  @Test
+  public void nullUrlIsLoaded() throws Exception {
+    String rootUrl = null;
+    OAuthServiceProvider provider = getGithubOAuthProvider(rootUrl);
+    assertThat(provider.getAuthorizationUrl()).isEqualTo(getExpectedUrl(rootUrl));
+  }
+
+  @Test
+  public void githubUrlIsLoaded() throws Exception {
+    String rootUrl = "https://github.com";
+    OAuthServiceProvider provider = getGithubOAuthProvider(rootUrl);
+    assertThat(provider.getAuthorizationUrl()).isEqualTo(getExpectedUrl(rootUrl));
+  }
+
+  @Test
+  public void githubUrlWithTrailingSlashIsLoaded() throws Exception {
+    String rootUrl = "https://github.com/";
+    OAuthServiceProvider provider = getGithubOAuthProvider(rootUrl);
+    assertThat(provider.getAuthorizationUrl()).isEqualTo(getExpectedUrl(rootUrl));
+  }
+
+  @Test
+  public void gheUrlIsLoaded() throws Exception {
+    String rootUrl = "https://git.yourcompany.com";
+    OAuthServiceProvider provider = getGithubOAuthProvider(rootUrl);
+    assertThat(provider.getAuthorizationUrl()).isEqualTo(getExpectedUrl(rootUrl));
+  }
+
+  @Test
+  public void gheUrlWithTrailingSlashIsLoaded() throws Exception {
+    String rootUrl = "https://git.yourcompany.com/";
+    OAuthServiceProvider provider = getGithubOAuthProvider(rootUrl);
+    assertThat(provider.getAuthorizationUrl()).isEqualTo(getExpectedUrl(rootUrl));
+  }
+}