// Copyright (C) 2008 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.httpd.rpc;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.gerrit.audit.AuditService;
import com.google.gerrit.audit.RpcAuditEvent;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.audit.Audit;
import com.google.gerrit.common.auth.SignInRequired;
import com.google.gerrit.common.errors.NotSignedInException;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.httpd.WebSession;
import com.google.gerrit.server.AccessPath;
import com.google.gerrit.server.CurrentUser;
import com.google.gson.GsonBuilder;
import com.google.gwtjsonrpc.common.RemoteJsonService;
import com.google.gwtjsonrpc.server.ActiveCall;
import com.google.gwtjsonrpc.server.JsonServlet;
import com.google.gwtjsonrpc.server.MethodHandle;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

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

/**
 * Base JSON servlet to ensure the current user is not forged.
 */
@SuppressWarnings("serial")
final class GerritJsonServlet extends JsonServlet<GerritJsonServlet.GerritCall> {
  private static final Logger log = LoggerFactory.getLogger(GerritJsonServlet.class);
  private static final ThreadLocal<GerritCall> currentCall =
      new ThreadLocal<>();
  private static final ThreadLocal<MethodHandle> currentMethod =
      new ThreadLocal<>();
  private final DynamicItem<WebSession> session;
  private final RemoteJsonService service;
  private final AuditService audit;


  @Inject
  GerritJsonServlet(final DynamicItem<WebSession> w, final RemoteJsonService s,
      final AuditService a) {
    session = w;
    service = s;
    audit = a;
  }

  @Override
  protected GerritCall createActiveCall(final HttpServletRequest req,
      final HttpServletResponse rsp) {
    final GerritCall call = new GerritCall(session.get(), req, new AuditedHttpServletResponse(rsp));
    currentCall.set(call);
    return call;
  }

  @Override
  protected GsonBuilder createGsonBuilder() {
    return gerritDefaultGsonBuilder();
  }

  private static GsonBuilder gerritDefaultGsonBuilder() {
    final GsonBuilder g = defaultGsonBuilder();

    g.registerTypeAdapter(org.eclipse.jgit.diff.Edit.class,
        new org.eclipse.jgit.diff.EditDeserializer());

    return g;
  }

  @Override
  protected void preInvoke(final GerritCall call) {
    super.preInvoke(call);

    if (call.isComplete()) {
      return;
    }

    if (call.getMethod().getAnnotation(SignInRequired.class) != null) {
      // If SignInRequired is set on this method we must have both a
      // valid XSRF token *and* have the user signed in. Doing these
      // checks also validates that they agree on the user identity.
      //
      if (!call.requireXsrfValid() || !session.get().isSignedIn()) {
        call.onFailure(new NotSignedInException());
      }
    }
  }

  @Override
  protected Object createServiceHandle() {
    return service;
  }

  @Override
  protected void service(final HttpServletRequest req,
      final HttpServletResponse resp) throws IOException {
    try {
      super.service(req, resp);
    } finally {
      audit();
      currentCall.set(null);
    }
  }

  private void audit() {
    try {
      GerritCall call = currentCall.get();
      MethodHandle method = call.getMethod();
      if (method == null) {
        return;
      }
      Audit note = method.getAnnotation(Audit.class);
      if (note != null) {
        final String sid = call.getWebSession().getSessionId();
        final CurrentUser username = call.getWebSession().getCurrentUser();
        final Multimap<String, ?> args =
            extractParams(note, call);
        final String what = extractWhat(note, call);
        final Object result = call.getResult();

        audit.dispatch(new RpcAuditEvent(sid, username, what, call.getWhen(),
            args, call.getHttpServletRequest().getMethod(), call.getHttpServletRequest().getMethod(),
            ((AuditedHttpServletResponse) (call.getHttpServletResponse()))
                .getStatus(), result));
      }
    } catch (Throwable all) {
      log.error("Unable to log the call", all);
    }
  }

  private Multimap<String, ?> extractParams(final Audit note, final GerritCall call) {
    Multimap<String, Object> args = ArrayListMultimap.create();

    Object[] params = call.getParams();
    for (int i = 0; i < params.length; i++) {
      args.put("$" + i, params[i]);
    }

    for (int idx : note.obfuscate()) {
      args.removeAll("$" + idx);
      args.put("$" + idx, "*****");
    }
    return args;
  }

  private String extractWhat(final Audit note, final GerritCall call) {
    String methodClass = call.getMethodClass().getName();
    methodClass = methodClass.substring(methodClass.lastIndexOf(".")+1);
    String what = note.action();
    if (what.length() == 0) {
      what = call.getMethod().getName();
    }

    return methodClass + "." + what;
  }

  static class GerritCall extends ActiveCall {
    private final WebSession session;
    private final long when;
    private static final Field resultField;
    private static final Field methodField;

    // Needed to allow access to non-public result field in GWT/JSON-RPC
    static {
      resultField = getPrivateField(ActiveCall.class, "result");
      methodField = getPrivateField(MethodHandle.class, "method");
    }

    private static Field getPrivateField(Class<?> clazz, String fieldName) {
      Field declaredField = null;
      try {
        declaredField = clazz.getDeclaredField(fieldName);
        declaredField.setAccessible(true);
      } catch (Exception e) {
        log.error("Unable to expose RPS/JSON result field");
      }
      return declaredField;
    }

    // Surrogate of the missing getMethodClass() in GWT/JSON-RPC
    public Class<?> getMethodClass() {
      if (methodField == null) {
        return null;
      }

      try {
        Method method = (Method) methodField.get(this.getMethod());
        return method.getDeclaringClass();
      } catch (IllegalArgumentException e) {
        log.error("Cannot access result field");
      } catch (IllegalAccessException e) {
        log.error("No permissions to access result field");
      }

      return null;
    }

    // Surrogate of the missing getResult() in GWT/JSON-RPC
    public Object getResult() {
      if (resultField == null) {
        return null;
      }

      try {
        return resultField.get(this);
      } catch (IllegalArgumentException e) {
        log.error("Cannot access result field");
      } catch (IllegalAccessException e) {
        log.error("No permissions to access result field");
      }

      return null;
    }

    GerritCall(final WebSession session, final HttpServletRequest i,
        final HttpServletResponse o) {
      super(i, o);
      this.session = session;
      this.when = TimeUtil.nowMs();
    }

    @Override
    public MethodHandle getMethod() {
      if (currentMethod.get() == null) {
        return super.getMethod();
      } else {
        return currentMethod.get();
      }
    }

    @Override
    public void onFailure(final Throwable error) {
      if (error instanceof IllegalArgumentException
          || error instanceof IllegalStateException) {
        super.onFailure(error);
      } else if (error instanceof OrmException
          || error instanceof RuntimeException) {
        onInternalFailure(error);
      } else {
        super.onFailure(error);
      }
    }

    @Override
    public boolean xsrfValidate() {
      final String keyIn = getXsrfKeyIn();
      if (keyIn == null || "".equals(keyIn)) {
        // Anonymous requests don't need XSRF protection, they shouldn't
        // be able to cause critical state changes.
        //
        return !session.isSignedIn();

      } else if (session.isSignedIn() && session.isValidXGerritAuth(keyIn)) {
        // The session must exist, and must be using this token.
        //
        session.getCurrentUser().setAccessPath(AccessPath.JSON_RPC);
        return true;
      }
      return false;
    }

    public WebSession getWebSession() {
      return session;
    }

    public long getWhen() {
      return when;
    }

    public long getElapsed() {
      return TimeUtil.nowMs() - when;
    }
  }

}
