// Copyright (C) 2010 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;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.Cache;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.gerrit.common.data.Capable;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.server.AccessPath;
import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.RequestInfo;
import com.google.gerrit.server.RequestListener;
import com.google.gerrit.server.audit.HttpAuditEvent;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.PermissionAwareRepositoryManager;
import com.google.gerrit.server.git.TracingHook;
import com.google.gerrit.server.git.TransferConfig;
import com.google.gerrit.server.git.UploadPackInitializer;
import com.google.gerrit.server.git.receive.AsyncReceiveCommits;
import com.google.gerrit.server.git.validators.UploadValidators;
import com.google.gerrit.server.group.GroupAuditService;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.ProjectPermission;
import com.google.gerrit.server.plugincontext.PluginSetContext;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import java.io.IOException;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.http.server.GitServlet;
import org.eclipse.jgit.http.server.GitSmartHttpTools;
import org.eclipse.jgit.http.server.ServletUtils;
import org.eclipse.jgit.http.server.resolver.AsIsFileService;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.PostUploadHook;
import org.eclipse.jgit.transport.PostUploadHookChain;
import org.eclipse.jgit.transport.PreUploadHook;
import org.eclipse.jgit.transport.PreUploadHookChain;
import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.transport.ServiceMayNotContinueException;
import org.eclipse.jgit.transport.UploadPack;
import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
import org.eclipse.jgit.transport.resolver.RepositoryResolver;
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import org.eclipse.jgit.transport.resolver.UploadPackFactory;

/** Serves Git repositories over HTTP. */
@Singleton
public class GitOverHttpServlet extends GitServlet {
  private static final long serialVersionUID = 1L;

  private static final String ATT_STATE = ProjectState.class.getName();
  private static final String ATT_ARC = AsyncReceiveCommits.class.getName();
  private static final String ID_CACHE = "adv_bases";

  public static final String URL_REGEX;

  static {
    StringBuilder url = new StringBuilder();
    url.append("^(?:/a)?(?:/p/|/)(.*/(?:info/refs");
    for (String name : GitSmartHttpTools.VALID_SERVICES) {
      url.append('|').append(name);
    }
    url.append("))$");
    URL_REGEX = url.toString();
  }

  static class Module extends AbstractModule {

    private final boolean enableReceive;

    Module(boolean enableReceive) {
      this.enableReceive = enableReceive;
    }

    @Override
    protected void configure() {
      bind(Resolver.class);
      bind(UploadFactory.class);
      bind(UploadFilter.class);
      bind(new TypeLiteral<ReceivePackFactory<HttpServletRequest>>() {})
          .to(enableReceive ? ReceiveFactory.class : DisabledReceiveFactory.class);
      bind(ReceiveFilter.class);
      install(
          new CacheModule() {
            @Override
            protected void configure() {
              cache(ID_CACHE, AdvertisedObjectsCacheKey.class, new TypeLiteral<Set<ObjectId>>() {})
                  .maximumWeight(4096)
                  .expireAfterWrite(Duration.ofMinutes(10));
            }
          });

      // Don't bind Metrics, which is bound in a parent injector in tests.
    }
  }

  @VisibleForTesting
  @Singleton
  public static class Metrics {
    // Recording requests separately in this class is only necessary because of a bug in the
    // implementation of the generic RequestMetricsFilter; see
    // https://gerrit-review.googlesource.com/c/gerrit/+/211692
    private final AtomicLong requestsStarted = new AtomicLong();

    void requestStarted() {
      requestsStarted.incrementAndGet();
    }

    public long getRequestsStarted() {
      return requestsStarted.get();
    }
  }

  static class HttpServletResponseWithStatusWrapper extends HttpServletResponseWrapper {
    private int responseStatus;

    HttpServletResponseWithStatusWrapper(HttpServletResponse response) {
      super(response);
      /* Even if we could read the status from response, we assume that it is all
       * fine because we entered the filter without any prior issues.
       * When Google will have upgraded to Servlet 3.0, we could actually
       * call response.getStatus() and the code will be clearer.
       */
      responseStatus = HttpServletResponse.SC_OK;
    }

    @Override
    public void setStatus(int sc) {
      responseStatus = sc;
      super.setStatus(sc);
    }

    @SuppressWarnings("deprecation")
    @Override
    public void setStatus(int sc, String sm) {
      responseStatus = sc;
      super.setStatus(sc, sm);
    }

    @Override
    public void sendError(int sc) throws IOException {
      this.responseStatus = sc;
      super.sendError(sc);
    }

    @Override
    public void sendError(int sc, String msg) throws IOException {
      this.responseStatus = sc;
      super.sendError(sc, msg);
    }

    @Override
    public void sendRedirect(String location) throws IOException {
      this.responseStatus = HttpServletResponse.SC_MOVED_TEMPORARILY;
      super.sendRedirect(location);
    }

    public int getResponseStatus() {
      return responseStatus;
    }
  }

  @Inject
  GitOverHttpServlet(
      Resolver resolver,
      UploadFactory upload,
      UploadFilter uploadFilter,
      ReceivePackFactory<HttpServletRequest> receive,
      ReceiveFilter receiveFilter) {
    setRepositoryResolver(resolver);
    setAsIsFileService(AsIsFileService.DISABLED);

    setUploadPackFactory(upload);
    addUploadPackFilter(uploadFilter);

    setReceivePackFactory(receive);
    addReceivePackFilter(receiveFilter);
  }

  private static String extractWhat(HttpServletRequest request) {
    StringBuilder commandName = new StringBuilder(request.getRequestURL());
    if (request.getQueryString() != null) {
      commandName.append("?").append(request.getQueryString());
    }
    return commandName.toString();
  }

  private static ListMultimap<String, String> extractParameters(HttpServletRequest request) {
    if (request.getQueryString() == null) {
      return ImmutableListMultimap.of();
    }
    // Explicit cast is required to compile under Servlet API 2.5, where the return type is raw Map.
    @SuppressWarnings("cast")
    Map<String, String[]> parameterMap = (Map<String, String[]>) request.getParameterMap();
    ImmutableListMultimap.Builder<String, String> b = ImmutableListMultimap.builder();
    parameterMap.forEach(b::putAll);
    return b.build();
  }

  static class Resolver implements RepositoryResolver<HttpServletRequest> {
    private final GitRepositoryManager manager;
    private final PermissionBackend permissionBackend;
    private final Provider<CurrentUser> userProvider;
    private final ProjectCache projectCache;

    @Inject
    Resolver(
        GitRepositoryManager manager,
        PermissionBackend permissionBackend,
        Provider<CurrentUser> userProvider,
        ProjectCache projectCache) {
      this.manager = manager;
      this.permissionBackend = permissionBackend;
      this.userProvider = userProvider;
      this.projectCache = projectCache;
    }

    @Override
    public Repository open(HttpServletRequest req, String projectName)
        throws RepositoryNotFoundException, ServiceNotAuthorizedException,
            ServiceNotEnabledException, ServiceMayNotContinueException {
      while (projectName.endsWith("/")) {
        projectName = projectName.substring(0, projectName.length() - 1);
      }

      if (projectName.endsWith(".git")) {
        // Be nice and drop the trailing ".git" suffix, which we never keep
        // in our database, but clients might mistakenly provide anyway.
        //
        projectName = projectName.substring(0, projectName.length() - 4);
        while (projectName.endsWith("/")) {
          projectName = projectName.substring(0, projectName.length() - 1);
        }
      }

      CurrentUser user = userProvider.get();
      user.setAccessPath(AccessPath.GIT);

      try {
        Project.NameKey nameKey = Project.nameKey(projectName);
        ProjectState state = projectCache.checkedGet(nameKey);
        if (state == null || !state.statePermitsRead()) {
          throw new RepositoryNotFoundException(nameKey.get());
        }
        req.setAttribute(ATT_STATE, state);

        try {
          permissionBackend.user(user).project(nameKey).check(ProjectPermission.ACCESS);
        } catch (AuthException e) {
          if (user instanceof AnonymousUser) {
            throw new ServiceNotAuthorizedException();
          }
          throw new ServiceNotEnabledException(e.getMessage());
        }

        return manager.openRepository(nameKey);
      } catch (IOException | PermissionBackendException err) {
        throw new ServiceMayNotContinueException(projectName + " unavailable", err);
      }
    }
  }

  static class UploadFactory implements UploadPackFactory<HttpServletRequest> {
    private final TransferConfig config;
    private final DynamicSet<PreUploadHook> preUploadHooks;
    private final DynamicSet<PostUploadHook> postUploadHooks;
    private final PluginSetContext<UploadPackInitializer> uploadPackInitializers;
    private final PermissionBackend permissionBackend;

    @Inject
    UploadFactory(
        TransferConfig tc,
        DynamicSet<PreUploadHook> preUploadHooks,
        DynamicSet<PostUploadHook> postUploadHooks,
        PluginSetContext<UploadPackInitializer> uploadPackInitializers,
        PermissionBackend permissionBackend) {
      this.config = tc;
      this.preUploadHooks = preUploadHooks;
      this.postUploadHooks = postUploadHooks;
      this.uploadPackInitializers = uploadPackInitializers;
      this.permissionBackend = permissionBackend;
    }

    @Override
    public UploadPack create(HttpServletRequest req, Repository repo) {
      ProjectState state = (ProjectState) req.getAttribute(ATT_STATE);
      UploadPack up =
          new UploadPack(
              PermissionAwareRepositoryManager.wrap(
                  repo, permissionBackend.currentUser().project(state.getNameKey())));
      up.setPackConfig(config.getPackConfig());
      up.setTimeout(config.getTimeout());
      up.setPreUploadHook(PreUploadHookChain.newChain(Lists.newArrayList(preUploadHooks)));
      up.setPostUploadHook(PostUploadHookChain.newChain(Lists.newArrayList(postUploadHooks)));
      String header = req.getHeader("Git-Protocol");
      if (header != null) {
        String[] params = header.split(":");
        up.setExtraParameters(Arrays.asList(params));
      }
      uploadPackInitializers.runEach(initializer -> initializer.init(state.getNameKey(), up));
      return up;
    }
  }

  static class UploadFilter implements Filter {
    private final UploadValidators.Factory uploadValidatorsFactory;
    private final PermissionBackend permissionBackend;
    private final Provider<CurrentUser> userProvider;
    private final GroupAuditService groupAuditService;
    private final Metrics metrics;
    private final PluginSetContext<RequestListener> requestListeners;

    @Inject
    UploadFilter(
        UploadValidators.Factory uploadValidatorsFactory,
        PermissionBackend permissionBackend,
        Provider<CurrentUser> userProvider,
        GroupAuditService groupAuditService,
        Metrics metrics,
        PluginSetContext<RequestListener> requestListeners) {
      this.uploadValidatorsFactory = uploadValidatorsFactory;
      this.permissionBackend = permissionBackend;
      this.userProvider = userProvider;
      this.groupAuditService = groupAuditService;
      this.metrics = metrics;
      this.requestListeners = requestListeners;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain next)
        throws IOException, ServletException {
      metrics.requestStarted();
      // The Resolver above already checked READ access for us.
      Repository repo = ServletUtils.getRepository(request);
      ProjectState state = (ProjectState) request.getAttribute(ATT_STATE);
      UploadPack up = (UploadPack) request.getAttribute(ServletUtils.ATTRIBUTE_HANDLER);
      PermissionBackend.ForProject perm =
          permissionBackend.currentUser().project(state.getNameKey());
      HttpServletResponseWithStatusWrapper responseWrapper =
          new HttpServletResponseWithStatusWrapper((HttpServletResponse) response);
      HttpServletRequest httpRequest = (HttpServletRequest) request;
      String sessionId = httpRequest.getSession().getId();

      try (TraceContext traceContext = TraceContext.open()) {
        RequestInfo requestInfo =
            RequestInfo.builder(
                    RequestInfo.RequestType.GIT_UPLOAD, userProvider.get(), traceContext)
                .project(state.getNameKey())
                .build();
        requestListeners.runEach(l -> l.onRequest(requestInfo));

        try {
          perm.check(ProjectPermission.RUN_UPLOAD_PACK);
        } catch (AuthException e) {
          GitSmartHttpTools.sendError(
              (HttpServletRequest) request,
              responseWrapper,
              HttpServletResponse.SC_FORBIDDEN,
              "upload-pack not permitted on this server");
          return;
        } catch (PermissionBackendException e) {
          responseWrapper.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
          throw new ServletException(e);
        }

        // We use getRemoteHost() here instead of getRemoteAddr() because REMOTE_ADDR
        // may have been overridden by a proxy server -- we'll try to avoid this.
        UploadValidators uploadValidators =
            uploadValidatorsFactory.create(state.getProject(), repo, request.getRemoteHost());
        up.setPreUploadHook(
            PreUploadHookChain.newChain(
                Lists.newArrayList(up.getPreUploadHook(), uploadValidators)));

        try (TracingHook tracingHook = new TracingHook()) {
          up.setProtocolV2Hook(tracingHook);
          next.doFilter(httpRequest, responseWrapper);
        }
      } finally {
        groupAuditService.dispatch(
            new HttpAuditEvent(
                sessionId,
                userProvider.get(),
                extractWhat(httpRequest),
                TimeUtil.nowMs(),
                extractParameters(httpRequest),
                httpRequest.getMethod(),
                httpRequest,
                responseWrapper.getResponseStatus(),
                responseWrapper));
      }
    }

    @Override
    public void init(FilterConfig config) {}

    @Override
    public void destroy() {}
  }

  static class ReceiveFactory implements ReceivePackFactory<HttpServletRequest> {
    private final AsyncReceiveCommits.Factory factory;
    private final Provider<CurrentUser> userProvider;

    @Inject
    ReceiveFactory(AsyncReceiveCommits.Factory factory, Provider<CurrentUser> userProvider) {
      this.factory = factory;
      this.userProvider = userProvider;
    }

    @Override
    public ReceivePack create(HttpServletRequest req, Repository db)
        throws ServiceNotAuthorizedException {
      final ProjectState state = (ProjectState) req.getAttribute(ATT_STATE);

      if (!(userProvider.get().isIdentifiedUser())) {
        // Anonymous users are not permitted to push.
        throw new ServiceNotAuthorizedException();
      }

      AsyncReceiveCommits arc =
          factory.create(state, userProvider.get().asIdentifiedUser(), db, null);
      ReceivePack rp = arc.getReceivePack();
      req.setAttribute(ATT_ARC, arc);
      return rp;
    }
  }

  static class DisabledReceiveFactory implements ReceivePackFactory<HttpServletRequest> {
    @Override
    public ReceivePack create(HttpServletRequest req, Repository db)
        throws ServiceNotEnabledException {
      throw new ServiceNotEnabledException();
    }
  }

  static class ReceiveFilter implements Filter {
    private final Cache<AdvertisedObjectsCacheKey, Set<ObjectId>> cache;
    private final PermissionBackend permissionBackend;
    private final Provider<CurrentUser> userProvider;
    private final GroupAuditService groupAuditService;
    private final Metrics metrics;

    @Inject
    ReceiveFilter(
        @Named(ID_CACHE) Cache<AdvertisedObjectsCacheKey, Set<ObjectId>> cache,
        PermissionBackend permissionBackend,
        Provider<CurrentUser> userProvider,
        GroupAuditService groupAuditService,
        Metrics metrics) {
      this.cache = cache;
      this.permissionBackend = permissionBackend;
      this.userProvider = userProvider;
      this.groupAuditService = groupAuditService;
      this.metrics = metrics;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
      metrics.requestStarted();
      boolean isGet = "GET".equalsIgnoreCase(((HttpServletRequest) request).getMethod());

      AsyncReceiveCommits arc = (AsyncReceiveCommits) request.getAttribute(ATT_ARC);

      // Send refs down the wire.
      ReceivePack rp = arc.getReceivePack();
      rp.getAdvertiseRefsHook().advertiseRefs(rp);

      ProjectState state = (ProjectState) request.getAttribute(ATT_STATE);
      HttpServletResponseWithStatusWrapper responseWrapper =
          new HttpServletResponseWithStatusWrapper((HttpServletResponse) response);
      HttpServletRequest httpRequest = (HttpServletRequest) request;
      Capable canUpload;
      try {
        try {
          permissionBackend
              .currentUser()
              .project(state.getNameKey())
              .check(ProjectPermission.RUN_RECEIVE_PACK);
          canUpload = arc.canUpload();
        } catch (AuthException e) {
          GitSmartHttpTools.sendError(
              httpRequest,
              responseWrapper,
              HttpServletResponse.SC_FORBIDDEN,
              "receive-pack not permitted on this server");
          return;
        } catch (PermissionBackendException e) {
          throw new RuntimeException(e);
        }
      } finally {
        groupAuditService.dispatch(
            new HttpAuditEvent(
                httpRequest.getSession().getId(),
                userProvider.get(),
                extractWhat(httpRequest),
                TimeUtil.nowMs(),
                extractParameters(httpRequest),
                httpRequest.getMethod(),
                httpRequest,
                responseWrapper.getResponseStatus(),
                responseWrapper));
      }

      if (canUpload != Capable.OK) {
        GitSmartHttpTools.sendError(
            httpRequest,
            responseWrapper,
            HttpServletResponse.SC_FORBIDDEN,
            "\n" + canUpload.getMessage());
        return;
      }

      if (!rp.isCheckReferencedObjectsAreReachable()) {
        chain.doFilter(request, responseWrapper);
        return;
      }

      if (!(userProvider.get().isIdentifiedUser())) {
        chain.doFilter(request, responseWrapper);
        return;
      }

      AdvertisedObjectsCacheKey cacheKey =
          AdvertisedObjectsCacheKey.create(userProvider.get().getAccountId(), state.getNameKey());

      if (isGet) {
        cache.invalidate(cacheKey);
      } else {
        Set<ObjectId> ids = cache.getIfPresent(cacheKey);
        if (ids != null) {
          rp.getAdvertisedObjects().addAll(ids);
          cache.invalidate(cacheKey);
        }
      }

      chain.doFilter(request, responseWrapper);

      if (isGet) {
        cache.put(cacheKey, Collections.unmodifiableSet(new HashSet<>(rp.getAdvertisedObjects())));
      }
    }

    @Override
    public void init(FilterConfig arg0) {}

    @Override
    public void destroy() {}
  }
}
