// Copyright (C) 2009 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.pgm.init;

import static com.google.gerrit.pgm.init.api.InitUtil.dnOf;

import com.google.gerrit.extensions.client.AuthType;
import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.gerrit.pgm.init.api.InitFlags;
import com.google.gerrit.pgm.init.api.InitStep;
import com.google.gerrit.pgm.init.api.Section;
import com.google.gwtjsonrpc.server.SignedToken;
import com.google.inject.Inject;
import com.google.inject.Singleton;

/** Initialize the {@code auth} configuration section. */
@Singleton
class InitAuth implements InitStep {
  private static final String RECEIVE = "receive";
  private static final String ENABLE_SIGNED_PUSH = "enableSignedPush";

  private final ConsoleUI ui;
  private final Section auth;
  private final Section ldap;
  private final Section receive;
  private final InitFlags flags;

  @Inject
  InitAuth(InitFlags flags, ConsoleUI ui, Section.Factory sections) {
    this.flags = flags;
    this.ui = ui;
    this.auth = sections.get("auth", null);
    this.ldap = sections.get("ldap", null);
    this.receive = sections.get(RECEIVE, null);
  }

  @Override
  public void run() {
    ui.header("User Authentication");

    initAuthType();
    if (auth.getSecure("registerEmailPrivateKey") == null) {
      auth.setSecure("registerEmailPrivateKey", SignedToken.generateRandomKey());
    }

    initSignedPush();
  }

  private void initAuthType() {
    AuthType authType =
        auth.select(
            "Authentication method",
            "type",
            flags.dev ? AuthType.DEVELOPMENT_BECOME_ANY_ACCOUNT : AuthType.OPENID);
    switch (authType) {
      case HTTP:
      case HTTP_LDAP:
        {
          String hdr = auth.get("httpHeader");
          if (ui.yesno(hdr != null, "Get username from custom HTTP header")) {
            auth.string("Username HTTP header", "httpHeader", "SM_USER");
          } else if (hdr != null) {
            auth.unset("httpHeader");
          }
          auth.string("SSO logout URL", "logoutUrl", null);
          break;
        }

      case CLIENT_SSL_CERT_LDAP:
      case CUSTOM_EXTENSION:
      case DEVELOPMENT_BECOME_ANY_ACCOUNT:
      case LDAP:
      case LDAP_BIND:
      case OAUTH:
      case OPENID:
      case OPENID_SSO:
        break;
    }

    switch (authType) {
      case LDAP:
      case LDAP_BIND:
      case HTTP_LDAP:
        {
          String server = ldap.string("LDAP server", "server", "ldap://localhost");
          if (server != null //
              && !server.startsWith("ldap://") //
              && !server.startsWith("ldaps://")) {
            if (ui.yesno(false, "Use SSL")) {
              server = "ldaps://" + server;
            } else {
              server = "ldap://" + server;
            }
            ldap.set("server", server);
          }

          ldap.string("LDAP username", "username", null);
          ldap.password("username", "password");

          String aBase = ldap.string("Account BaseDN", "accountBase", dnOf(server));
          ldap.string("Group BaseDN", "groupBase", aBase);
          break;
        }

      case CLIENT_SSL_CERT_LDAP:
      case CUSTOM_EXTENSION:
      case DEVELOPMENT_BECOME_ANY_ACCOUNT:
      case HTTP:
      case OAUTH:
      case OPENID:
      case OPENID_SSO:
        break;
    }
  }

  private void initSignedPush() {
    boolean def = flags.cfg.getBoolean(RECEIVE, ENABLE_SIGNED_PUSH, false);
    boolean enable = ui.yesno(def, "Enable signed push support");
    receive.set("enableSignedPush", Boolean.toString(enable));
  }
}

@@ -639,16 +639,322 @@
 .init;%0A%0A
+import static com.google.gerrit.extensions.client.GitBasicAuthPolicy.HTTP;%0Aimport static com.google.gerrit.extensions.client.GitBasicAuthPolicy.HTTP_LDAP;%0Aimport static com.google.gerrit.extensions.client.GitBasicAuthPolicy.LDAP;%0Aimport static com.google.gerrit.extensions.client.GitBasicAuthPolicy.OAUTH;%0A
 import s
@@ -1059,16 +1059,79 @@
 thType;%0A
+import com.google.gerrit.extensions.client.GitBasicAuthPolicy;%0A
 import c
@@ -1432,16 +1432,42 @@
 ngleton;
+%0Aimport java.util.EnumSet;
 %0A%0A/** In
@@ -3036,32 +3036,699 @@
 eak;%0A        %7D%0A%0A
+      case LDAP:%0A        %7B%0A          auth.select(%0A              %22Git/HTTP authentication%22,%0A              %22gitBasicAuthPolicy%22,%0A              HTTP,%0A              EnumSet.of(HTTP, HTTP_LDAP, LDAP));%0A          break;%0A        %7D%0A      case OAUTH:%0A        %7B%0A          GitBasicAuthPolicy gitBasicAuth =%0A              auth.select(%0A                  %22Git/HTTP authentication%22, %22gitBasicAuthPolicy%22, HTTP, EnumSet.of(HTTP, OAUTH));%0A%0A          if (gitBasicAuth == OAUTH) %7B%0A            ui.message(%0A                %22*WARNING* Please make sure that your chosen OAuth provider%5Cn%22%0A                    + %22supports Git token authentication.%5Cn%22);%0A          %7D%0A          break;%0A        %7D%0A
       case CLIEN
@@ -3736,32 +3736,32 @@
 _SSL_CERT_LDAP:%0A
-
       case CUSTO
@@ -3816,33 +3816,16 @@
 CCOUNT:%0A
-      case LDAP:%0A
       ca
@@ -3838,34 +3838,16 @@
 P_BIND:%0A
-      case OAUTH:%0A
       ca

Set Git/HTTP auth policy at init for LDAP, OAUTH