// 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.server;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.SignInDialog;
import com.google.gerrit.client.SignInDialog.Mode;
import com.google.gerrit.client.openid.DiscoveryResult;
import com.google.gerrit.client.openid.OpenIdService;
import com.google.gerrit.client.openid.OpenIdUtil;
import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountExternalId;
import com.google.gerrit.client.reviewdb.AccountExternalIdAccess;
import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gerrit.client.reviewdb.SystemConfig;
import com.google.gerrit.client.rpc.Common;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwtjsonrpc.server.ValidToken;
import com.google.gwtjsonrpc.server.XsrfException;
import com.google.gwtorm.client.KeyUtil;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.ResultSet;
import com.google.gwtorm.client.Transaction;

import net.sf.ehcache.Element;
import net.sf.ehcache.constructs.blocking.CacheEntryFactory;
import net.sf.ehcache.constructs.blocking.SelfPopulatingCache;

import org.openid4java.consumer.ConsumerException;
import org.openid4java.consumer.ConsumerManager;
import org.openid4java.consumer.VerificationResult;
import org.openid4java.discovery.DiscoveryException;
import org.openid4java.discovery.DiscoveryInformation;
import org.openid4java.discovery.Identifier;
import org.openid4java.message.AuthRequest;
import org.openid4java.message.Message;
import org.openid4java.message.MessageException;
import org.openid4java.message.MessageExtension;
import org.openid4java.message.ParameterList;
import org.openid4java.message.ax.AxMessage;
import org.openid4java.message.ax.FetchRequest;
import org.openid4java.message.ax.FetchResponse;
import org.openid4java.message.sreg.SRegMessage;
import org.openid4java.message.sreg.SRegRequest;
import org.openid4java.message.sreg.SRegResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TreeMap;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

class OpenIdServiceImpl implements OpenIdService {
  private static final Logger log =
      LoggerFactory.getLogger(OpenIdServiceImpl.class);

  private static final String P_MODE = "gerrit.mode";
  private static final String P_TOKEN = "gerrit.token";
  private static final String P_REMEMBER = "gerrit.remember";
  private static final int LASTID_AGE = 365 * 24 * 60 * 60; // seconds

  private static final String OPENID_MODE = "openid.mode";
  private static final String OMODE_CANCEL = "cancel";

  private static final String SCHEMA_EMAIL =
      "http://schema.openid.net/contact/email";
  private static final String SCHEMA_FIRSTNAME =
      "http://schema.openid.net/namePerson/first";
  private static final String SCHEMA_LASTNAME =
      "http://schema.openid.net/namePerson/last";

  private static OpenIdServiceImpl INSTANCE;

  private static boolean useOpenID() {
    return Common.getGerritConfig().getLoginType() == SystemConfig.LoginType.OPENID;
  }

  static synchronized OpenIdServiceImpl getInstance() throws ConsumerException,
      OrmException, XsrfException {
    if (INSTANCE == null) {
      INSTANCE = new OpenIdServiceImpl();
    }
    return INSTANCE;
  }

  private final GerritServer server;
  private final ConsumerManager manager;
  private final SelfPopulatingCache discoveryCache;

  private OpenIdServiceImpl() throws ConsumerException, OrmException,
      XsrfException {
    server = GerritServer.getInstance();
    manager = new ConsumerManager();
    if (useOpenID()) {
      discoveryCache =
          new SelfPopulatingCache(server.getCache("openid"),
              new CacheEntryFactory() {
                public Object createEntry(final Object objKey) throws Exception {
                  try {
                    final List<?> list = manager.discover((String) objKey);
                    return list != null && !list.isEmpty() ? list : null;
                  } catch (DiscoveryException e) {
                    return null;
                  }
                }
              });
    } else {
      discoveryCache = null;
    }
  }

  public void discover(final String openidIdentifier,
      final SignInDialog.Mode mode, final boolean remember,
      final String returnToken, final AsyncCallback<DiscoveryResult> callback) {
    if (!useOpenID()) {
      callback.onFailure(new IllegalStateException("OpenID not enabled"));
      return;
    }

    final HttpServletRequest httpReq =
        GerritJsonServlet.getCurrentCall().getHttpServletRequest();
    final State state;
    state = init(httpReq, openidIdentifier, mode, remember, returnToken);
    if (state == null) {
      callback.onSuccess(new DiscoveryResult(false));
      return;
    }

    final AuthRequest aReq;
    try {
      aReq = manager.authenticate(state.discovered, state.retTo.toString());
      aReq.setRealm(state.contextUrl);

      if (requestRegistration(aReq)) {
        final SRegRequest sregReq = SRegRequest.createFetchRequest();
        sregReq.addAttribute("fullname", true);
        sregReq.addAttribute("email", true);
        aReq.addExtension(sregReq);

        final FetchRequest fetch = FetchRequest.createFetchRequest();
        fetch.addAttribute("FirstName", SCHEMA_FIRSTNAME, true);
        fetch.addAttribute("LastName", SCHEMA_LASTNAME, true);
        fetch.addAttribute("Email", SCHEMA_EMAIL, true);
        aReq.addExtension(fetch);
      }
    } catch (MessageException e) {
      callback.onSuccess(new DiscoveryResult(false));
      return;
    } catch (ConsumerException e) {
      callback.onSuccess(new DiscoveryResult(false));
      return;
    }

    callback.onSuccess(new DiscoveryResult(true, aReq.getDestinationUrl(false),
        aReq.getParameterMap()));
  }

  private boolean requestRegistration(final AuthRequest aReq) {
    if (AuthRequest.SELECT_ID.equals(aReq.getIdentity())) {
      // We don't know anything about the identity, as the provider
      // will offer the user a way to indicate their identity. Skip
      // any database query operation and assume we must ask for the
      // registration information, in case the identity is new to us.
      //
      return true;
    }

    // We might already have this account on file. Look for it.
    //
    try {
      final ReviewDb db = Common.getSchemaFactory().open();
      try {
        final ResultSet<AccountExternalId> ae =
            db.accountExternalIds().byExternal(aReq.getIdentity());
        if (ae.iterator().hasNext()) {
          // We already have it. Don't bother asking for the
          // registration information, we have what we need.
          //
          return false;
        }
      } finally {
        db.close();
      }
    } catch (OrmException e) {
      log.warn("Failed looking for existing account", e);
    }

    // We don't have this account on file, or our query failed. Assume
    // we should ask for registration information in case the account
    // turns out to be new.
    //
    return true;
  }

  /** Called by {@link OpenIdLoginServlet} doGet, doPost */
  void doAuth(final HttpServletRequest req, final HttpServletResponse rsp)
      throws Exception {
    if (false) {
      debugRequest(req);
    }

    final String openidMode = req.getParameter(OPENID_MODE);
    if (OMODE_CANCEL.equals(openidMode)) {
      cancel(req, rsp);

    } else {
      // Process the authentication response.
      //
      final SignInDialog.Mode mode = signInMode(req);
      final String openidIdentifier = req.getParameter("openid.identity");
      final String returnToken = req.getParameter(P_TOKEN);
      final boolean remember = "1".equals(req.getParameter(P_REMEMBER));
      final State state;

      state = init(req, openidIdentifier, mode, remember, returnToken);
      if (state == null) {
        // Re-discovery must have failed, we can't run a login.
        //
        cancel(req, rsp);
        return;
      }

      final String returnTo = req.getParameter("openid.return_to");
      if (returnTo != null && returnTo.contains("openid.rpnonce=")) {
        // Some providers (claimid.com) seem to embed these request
        // parameters into our return_to URL, and then give us them
        // in the return_to request parameter. But not all.
        //
        state.retTo.put("openid.rpnonce", req.getParameter("openid.rpnonce"));
        state.retTo.put("openid.rpsig", req.getParameter("openid.rpsig"));
      }

      final VerificationResult result =
          manager.verify(state.retTo.toString(), new ParameterList(req
              .getParameterMap()), state.discovered);
      final Identifier user = result.getVerifiedId();

      if (user != null) {
        // Authentication was successful.
        //
        final Message authRsp = result.getAuthResponse();
        SRegResponse sregRsp = null;
        FetchResponse fetchRsp = null;

        if (authRsp.hasExtension(SRegMessage.OPENID_NS_SREG)) {
          final MessageExtension ext =
              authRsp.getExtension(SRegMessage.OPENID_NS_SREG);
          if (ext instanceof SRegResponse) {
            sregRsp = (SRegResponse) ext;
          }
        }

        if (authRsp.hasExtension(AxMessage.OPENID_NS_AX)) {
          final MessageExtension ext =
              authRsp.getExtension(AxMessage.OPENID_NS_AX);
          if (ext instanceof FetchResponse) {
            fetchRsp = (FetchResponse) ext;
          }
        }

        String fullname = null;
        String email = null;

        if (sregRsp != null) {
          fullname = sregRsp.getAttributeValue("fullname");
          email = sregRsp.getAttributeValue("email");

        } else if (fetchRsp != null) {
          final String firstName = fetchRsp.getAttributeValue("FirstName");
          final String lastName = fetchRsp.getAttributeValue("LastName");
          final StringBuilder n = new StringBuilder();
          if (firstName != null && firstName.length() > 0) {
            n.append(firstName);
          }
          if (lastName != null && lastName.length() > 0) {
            if (n.length() > 0) {
              n.append(' ');
            }
            n.append(lastName);
          }
          fullname = n.length() > 0 ? n.toString() : null;
          email = fetchRsp.getAttributeValue("Email");
        }

        initializeAccount(req, rsp, user, fullname, email);
      } else if ("Nonce verification failed.".equals(result.getStatusMsg())) {
        // We might be suffering from clock skew on this system.
        //
        log.error("OpenID failure: " + result.getStatusMsg()
            + "  Likely caused by clock skew on this server,"
            + " install/configure NTP.");
        cancelWithError(req, rsp, mode, result.getStatusMsg());
      } else if (result.getStatusMsg() != null) {
        // Authentication failed.
        //
        log.error("OpenID failure: " + result.getStatusMsg());
        cancelWithError(req, rsp, mode, result.getStatusMsg());
      } else {
        // Assume authentication was canceled.
        //
        cancel(req, rsp);
      }
    }
  }

  @SuppressWarnings("unchecked")
  private static void debugRequest(final HttpServletRequest req) {
    System.err.println(req.getMethod() + " /login");
    for (final String n : new TreeMap<String, Object>(req.getParameterMap())
        .keySet()) {
      for (final String v : req.getParameterValues(n)) {
        System.err.println("  " + n + "=" + v);
      }
    }
    System.err.println();
  }

  private void initializeAccount(final HttpServletRequest req,
      final HttpServletResponse rsp, final Identifier user,
      final String fullname, final String email) throws IOException {
    final SignInDialog.Mode mode = signInMode(req);
    Account account = null;
    if (user != null) {
      try {
        final ReviewDb d = Common.getSchemaFactory().open();
        try {
          switch (mode) {
            case SIGN_IN:
              account = openAccount(d, user, fullname, email);
              break;
            case LINK_IDENTIY:
              account = linkAccount(req, d, user, email);
              break;
          }
        } finally {
          d.close();
        }
      } catch (OrmException e) {
        log.error("Account lookup failed", e);
        account = null;
      }
    }

    Cookie c = new Cookie(Gerrit.ACCOUNT_COOKIE, "");
    c.setPath(req.getContextPath() + "/");

    if (account == null) {
      if (mode == SignInDialog.Mode.SIGN_IN) {
        c.setMaxAge(0);
        rsp.addCookie(c);
      }
      cancel(req, rsp);

    } else if (mode == SignInDialog.Mode.SIGN_IN) {
      final boolean remember = "1".equals(req.getParameter(P_REMEMBER));

      new AccountCookie(account.getId(), remember).set(c, server);
      rsp.addCookie(c);

      c = new Cookie(OpenIdUtil.LASTID_COOKIE, "");
      c.setPath(req.getContextPath() + "/");
      if (remember) {
        c.setValue(user.getIdentifier());
        c.setMaxAge(LASTID_AGE);
      } else {
        c.setMaxAge(0);
      }
      rsp.addCookie(c);

      callback(req, rsp);

    } else {
      callback(req, rsp);
    }
  }

  private Account openAccount(final ReviewDb db, final Identifier user,
      final String fullname, final String email) throws OrmException {
    Account account;
    final AccountExternalIdAccess extAccess = db.accountExternalIds();
    AccountExternalId acctExt = lookup(extAccess, user.getIdentifier());

    if (acctExt == null && email != null
        && server.isAllowGoogleAccountUpgrade() && isGoogleAccount(user)) {
      acctExt = lookupGoogleAccount(extAccess, email);
      if (acctExt != null) {
        // Legacy user from Gerrit 1? Attach the OpenID identity.
        //
        final AccountExternalId openidExt =
            new AccountExternalId(new AccountExternalId.Key(acctExt
                .getAccountId(), user.getIdentifier()));
        extAccess.insert(Collections.singleton(openidExt));
        acctExt = openidExt;
      }
    }

    if (acctExt != null) {
      // Existing user; double check the email is current.
      //
      if (email != null && !email.equals(acctExt.getEmailAddress())) {
        acctExt.setEmailAddress(email);
      }
      acctExt.setLastUsedOn();
      extAccess.update(Collections.singleton(acctExt));
      account = Common.getAccountCache().get(acctExt.getAccountId(), db);
    } else {
      account = null;
    }

    if (account == null) {
      // New user; create an account entity for them.
      //
      final Transaction txn = db.beginTransaction();

      account = new Account(new Account.Id(db.nextAccountId()));
      account.setFullName(fullname);
      account.setPreferredEmail(email);

      acctExt =
          new AccountExternalId(new AccountExternalId.Key(account.getId(), user
              .getIdentifier()));
      acctExt.setLastUsedOn();
      acctExt.setEmailAddress(email);

      db.accounts().insert(Collections.singleton(account), txn);
      extAccess.insert(Collections.singleton(acctExt), txn);
      txn.commit();
    }
    return account;
  }

  private Account linkAccount(final HttpServletRequest req, final ReviewDb db,
      final Identifier user, final String email) throws OrmException {
    final Cookie[] cookies = req.getCookies();
    if (cookies == null) {
      return null;
    }
    Account.Id me = null;
    for (final Cookie c : cookies) {
      if (Gerrit.ACCOUNT_COOKIE.equals(c.getName())) {
        try {
          final ValidToken tok =
              server.getAccountToken().checkToken(c.getValue(), null);
          if (tok == null) {
            return null;
          }
          me = AccountCookie.parse(tok).getAccountId();
          break;
        } catch (XsrfException e) {
          return null;
        } catch (RuntimeException e) {
          return null;
        }
      }
    }
    if (me == null) {
      return null;
    }

    final Account account = Common.getAccountCache().get(me, db);
    if (account == null) {
      return null;
    }

    final AccountExternalId.Key idKey =
        new AccountExternalId.Key(account.getId(), user.getIdentifier());
    AccountExternalId id = db.accountExternalIds().get(idKey);
    if (id == null) {
      id = new AccountExternalId(idKey);
      id.setLastUsedOn();
      id.setEmailAddress(email);
      db.accountExternalIds().insert(Collections.singleton(id));
      Common.getGroupCache().invalidate(account.getId());
    } else {
      if (email != null && !email.equals(id.getEmailAddress())) {
        id.setEmailAddress(email);
      }
      id.setLastUsedOn();
      db.accountExternalIds().update(Collections.singleton(id));
    }
    return account;
  }

  private static Mode signInMode(final HttpServletRequest req) {
    try {
      return SignInDialog.Mode.valueOf(req.getParameter(P_MODE));
    } catch (RuntimeException e) {
      return SignInDialog.Mode.SIGN_IN;
    }
  }

  private static AccountExternalId lookup(
      final AccountExternalIdAccess extAccess, final String id)
      throws OrmException {
    final List<AccountExternalId> extRes = extAccess.byExternal(id).toList();
    switch (extRes.size()) {
      case 0:
        return null;
      case 1:
        return extRes.get(0);
      default:
        throw new OrmException("More than one account matches: " + id);
    }
  }

  private static boolean isGoogleAccount(final Identifier user) {
    return user.getIdentifier().startsWith(OpenIdUtil.URL_GOOGLE + "?");
  }

  private static AccountExternalId lookupGoogleAccount(
      final AccountExternalIdAccess extAccess, final String email)
      throws OrmException {
    // We may have multiple records which match the email address, but
    // all under the same account. This happens when the user does a
    // login through different server hostnames, as Google issues
    // unique OpenID tokens per server.
    //
    // Match to an existing account only if there is exactly one record
    // for this email using the generic Google identity.
    //
    final List<AccountExternalId> m = new ArrayList<AccountExternalId>();
    for (final AccountExternalId e : extAccess.byEmailAddress(email)) {
      if (e.getExternalId().equals("Google Account " + email)) {
        m.add(e);
      }
    }
    return m.size() == 1 ? m.get(0) : null;
  }

  private static void callback(final HttpServletRequest req,
      final HttpServletResponse rsp) throws IOException {
    final StringBuilder rdr = new StringBuilder();
    rdr.append(GerritServer.serverUrl(req));
    final String token = req.getParameter(P_TOKEN);
    if (token != null && !token.startsWith("SignInFailure,")) {
      rdr.append('#');
      rdr.append(token);
    }
    rsp.sendRedirect(rdr.toString());
  }

  private static void cancel(final HttpServletRequest req,
      final HttpServletResponse rsp) throws IOException {
    callback(req, rsp);
  }

  private static void cancelWithError(final HttpServletRequest req,
      final HttpServletResponse rsp, final SignInDialog.Mode mode,
      final String errorDetail) throws IOException {
    final StringBuilder rdr = new StringBuilder();
    rdr.append(GerritServer.serverUrl(req));
    rdr.append('#');
    rdr.append("SignInFailure");
    rdr.append(',');
    rdr.append(mode.name());
    rdr.append(',');
    rdr.append(errorDetail != null ? KeyUtil.encode(errorDetail) : "");
    rsp.sendRedirect(rdr.toString());
  }

  private State init(final HttpServletRequest httpReq,
      final String openidIdentifier, final SignInDialog.Mode mode,
      final boolean remember, final String returnToken) {
    final Element serverCache = discoveryCache.get(openidIdentifier);
    if (serverCache == null) {
      return null;
    }

    final List<?> list = (List<?>) serverCache.getObjectValue();
    if (list == null || list.isEmpty()) {
      return null;
    }

    String contextUrl = server.getCanonicalURL();
    if (contextUrl == null) {
      contextUrl = GerritServer.serverUrl(httpReq);
    }
    final DiscoveryInformation discovered = manager.associate(list);
    final UrlEncoded retTo = new UrlEncoded(contextUrl + "login");
    retTo.put(P_MODE, mode.name());
    if (returnToken != null && returnToken.length() > 0) {
      retTo.put(P_TOKEN, returnToken);
    }
    if (remember) {
      retTo.put(P_REMEMBER, "1");
    }
    return new State(discovered, retTo, contextUrl);
  }

  private static class State {
    final DiscoveryInformation discovered;
    final UrlEncoded retTo;
    final String contextUrl;

    State(final DiscoveryInformation d, final UrlEncoded r, final String c) {
      discovered = d;
      retTo = r;
      contextUrl = c;
    }
  }
}
