Add 'git-lfs-authenticate' SSH-API implementation

This is greatly inspired on [1] (thanks Remy :)), but it goes into
different direction as it is based on [2] therefore I have decided to
implement it as separate feature instead of PS for [1].

[1] https://gerrit-review.googlesource.com/#/c/93393/
[2] https://gerrit-review.googlesource.com/#/c/93673/

Depends-On: 72aa5254dfb5b8299c3999990d5495887ced62a0
Change-Id: Ic23d8c82b07ed6a3e0084ed9a0827f3406e4cad4
Signed-off-by: Jacek Centkowski <geminica.programs@gmail.com>
diff --git a/BUCK b/BUCK
index db9e942..409fd6d 100644
--- a/BUCK
+++ b/BUCK
@@ -20,6 +20,7 @@
     'Gerrit-PluginName: lfs',
     'Gerrit-Module: com.googlesource.gerrit.plugins.lfs.Module',
     'Gerrit-HttpModule: com.googlesource.gerrit.plugins.lfs.HttpModule',
+    'Gerrit-SshModule: com.googlesource.gerrit.plugins.lfs.SshModule',
   ],
 )
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/lfs/LfsSshAuth.java b/src/main/java/com/googlesource/gerrit/plugins/lfs/LfsSshAuth.java
new file mode 100644
index 0000000..d82abff
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/lfs/LfsSshAuth.java
@@ -0,0 +1,72 @@
+// Copyright (C) 2017 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.lfs;
+
+import static org.eclipse.jgit.util.HttpSupport.HDR_AUTHORIZATION;
+
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.config.CanonicalWebUrl;
+import com.google.gerrit.sshd.BaseCommand.Failure;
+import com.google.gerrit.sshd.BaseCommand.UnloggedFailure;
+import com.google.gerrit.sshd.plugin.LfsPluginAuthCommand;
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+import org.eclipse.jgit.lfs.server.Response;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+
+@Singleton
+public class LfsSshAuth implements LfsPluginAuthCommand.LfsSshPluginAuth {
+  private final String canonicalWebUrl;
+  private final Gson gson;
+
+  @Inject
+  LfsSshAuth(@CanonicalWebUrl Provider<String> canonicalWebUrl) {
+    this.canonicalWebUrl = canonicalWebUrl.get();
+    this.gson = new GsonBuilder()
+        .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
+        .disableHtmlEscaping()
+        .create();
+  }
+
+  @Override
+  public String authenticate(CurrentUser user, List<String> args)
+      throws UnloggedFailure, Failure {
+    try {
+      URL url = new URL(canonicalWebUrl);
+      String href = url.getProtocol() + "://" + url.getAuthority()
+          + url.getPath() + "/" + args.get(0) + "/info/lfs";
+      Response.Action response = new Response.Action();
+      response.href = href;
+      response.header =
+          Collections.singletonMap(HDR_AUTHORIZATION, "not:required");
+
+      return gson.toJson(response);
+
+    } catch (MalformedURLException e) {
+      throw new Failure(1, "Server configuration error: "
+          + "forming Git LFS endpoint URL from canonicalWebUrl ["
+          + canonicalWebUrl + "] failed.");
+    }
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/lfs/SshModule.java b/src/main/java/com/googlesource/gerrit/plugins/lfs/SshModule.java
new file mode 100644
index 0000000..816e0a1
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/lfs/SshModule.java
@@ -0,0 +1,28 @@
+// Copyright (C) 2017 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.lfs;
+
+import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.gerrit.sshd.PluginCommandModule;
+import com.google.gerrit.sshd.plugin.LfsPluginAuthCommand;
+
+public class SshModule extends PluginCommandModule {
+
+  @Override
+  protected void configureCommands() {
+    DynamicItem.bind(binder(), LfsPluginAuthCommand.LfsSshPluginAuth.class)
+      .to(LfsSshAuth.class);
+  }
+}