Merge branch 'stable-2.16'
* stable-2.16: ssh: Allow GIT_PROTOCOL to contain multiple parameters Fix running Gerrit on Tomcat Fix too-aggressive shortcut Filter MERGE_LIST magic file from Prolog facts Allow to enable git protocol version 2 for upload pack Remove irrelevant styles Remove unneeded AuditServiceImpl Fix some reviewers emails showing as undefined Add shift+m shortcut to diff view Delete system config table Don't use List in GerritConfigListener API Revert "Revert "Show author and committer when relevant"" Reload repo and group list after creating a repo or group Hide "private" check box if private changes are disabled Set version to 2.15.7 Trigger audit for GIT over Http commands Change-Id: Idf8aed46f7a4fc1cd9b2630f79c73b86eefd970f
This commit is contained in:
		@@ -27,15 +27,14 @@ If the `gerrit.site_path` system property is defined then the init is
 | 
			
		||||
run for that site. The database connectivity, in that case, is defined
 | 
			
		||||
in the `etc/gerrit.config`.
 | 
			
		||||
 | 
			
		||||
If `gerrit.site_path` is not defined then Gerrit will try to find the
 | 
			
		||||
`gerrit.init_path` system property. If defined this property will be
 | 
			
		||||
used to determine the site path. The database connectivity, also for
 | 
			
		||||
this case, is defined by the `jdbc/ReviewDb` JNDI property.
 | 
			
		||||
`gerrit.site_path` system property must be defined to run the init for
 | 
			
		||||
that site.
 | 
			
		||||
 | 
			
		||||
[WARNING]
 | 
			
		||||
Defining the `jdbc/ReviewDb` JNDI property for an H2 database under the
 | 
			
		||||
path defined by either `gerrit.site_path` or `gerrit.init_path` will
 | 
			
		||||
cause an incomplete auto initialization and Gerrit will fail to start.
 | 
			
		||||
path defined by `gerrit.site_path` will cause an incomplete auto
 | 
			
		||||
initialization and Gerrit will fail to start.
 | 
			
		||||
 | 
			
		||||
Opening a connection to such a database will create a subfolder under the
 | 
			
		||||
site path folder (in order to create the H2 database) and Gerrit will
 | 
			
		||||
no longer consider that site path to be new and, because of that,
 | 
			
		||||
 
 | 
			
		||||
@@ -3798,6 +3798,20 @@ link:https://www.gnupg.org/documentation/manuals/gnupg/OpenPGP-Key-Management.ht
 | 
			
		||||
If no keys are specified, web-of-trust checks are disabled. This is the
 | 
			
		||||
default behavior.
 | 
			
		||||
 | 
			
		||||
[[receive.enableProtocolV2]]receive.enableProtocolV2::
 | 
			
		||||
+
 | 
			
		||||
Enable support for git protocol version 2.
 | 
			
		||||
+
 | 
			
		||||
When this option is enabled, clients may send upload pack using git
 | 
			
		||||
protocol version 2.
 | 
			
		||||
+
 | 
			
		||||
The repository must also be configured on the server side to use protocol
 | 
			
		||||
version 2 by setting `protocol.version = 2` either in the gerrit user's
 | 
			
		||||
`~/.gitconfig` file (which will enable it for all repositories) or on
 | 
			
		||||
a per repository basis by setting the option in the `.git/config` file
 | 
			
		||||
of the repository.
 | 
			
		||||
+
 | 
			
		||||
Defaults to false, git protocol version 2 is not enabled.
 | 
			
		||||
 | 
			
		||||
[[repository]]
 | 
			
		||||
=== Section repository
 | 
			
		||||
@@ -5081,16 +5095,9 @@ command.
 | 
			
		||||
 | 
			
		||||
The format is one Base-64 encoded public key per line.
 | 
			
		||||
 | 
			
		||||
== Configuring the Polygerrit UI
 | 
			
		||||
 | 
			
		||||
== Database system_config
 | 
			
		||||
 | 
			
		||||
Several columns in the `system_config` table within the metadata
 | 
			
		||||
database may be set to control how Gerrit behaves.
 | 
			
		||||
 | 
			
		||||
[NOTE]
 | 
			
		||||
The contents of the `system_config` table are cached at startup
 | 
			
		||||
by Gerrit.  If you modify any columns in this table, Gerrit needs
 | 
			
		||||
to be restarted before it will use the new values.
 | 
			
		||||
Please see link:dev-polygerrit.html[UI] on configuring the Polygerrit UI.
 | 
			
		||||
 | 
			
		||||
=== Configurable Parameters
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -105,9 +105,8 @@ script and modify it for your configuration:
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
[TIP]
 | 
			
		||||
Under Jetty, restarting the web application (e.g. after modifying
 | 
			
		||||
`system_config`) is as simple as touching the context config file:
 | 
			
		||||
`'$JETTY_HOME'/contexts/gerrit.xml`
 | 
			
		||||
Under Jetty, restarting the web application is as simple as
 | 
			
		||||
touching the context config file: `'$JETTY_HOME'/contexts/gerrit.xml`
 | 
			
		||||
 | 
			
		||||
[[tomcat]]
 | 
			
		||||
== Tomcat 7.x
 | 
			
		||||
 
 | 
			
		||||
@@ -126,6 +126,7 @@ import com.google.gerrit.server.update.BatchUpdate;
 | 
			
		||||
import com.google.gerrit.testing.ConfigSuite;
 | 
			
		||||
import com.google.gerrit.testing.FakeEmailSender;
 | 
			
		||||
import com.google.gerrit.testing.FakeEmailSender.Message;
 | 
			
		||||
import com.google.gerrit.testing.FakeGroupAuditService;
 | 
			
		||||
import com.google.gerrit.testing.NoteDbMode;
 | 
			
		||||
import com.google.gerrit.testing.SshMode;
 | 
			
		||||
import com.google.gerrit.testing.TempFileUtil;
 | 
			
		||||
@@ -242,6 +243,7 @@ public abstract class AbstractDaemonTest {
 | 
			
		||||
  @Inject protected ChangeNoteUtil changeNoteUtil;
 | 
			
		||||
  @Inject protected ChangeResource.Factory changeResourceFactory;
 | 
			
		||||
  @Inject protected FakeEmailSender sender;
 | 
			
		||||
  @Inject protected FakeGroupAuditService auditService;
 | 
			
		||||
  @Inject protected GerritApi gApi;
 | 
			
		||||
  @Inject protected GitRepositoryManager repoManager;
 | 
			
		||||
  @Inject protected GroupBackend groupBackend;
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,7 @@ import com.google.gerrit.server.util.OneOffRequestContext;
 | 
			
		||||
import com.google.gerrit.server.util.SocketUtil;
 | 
			
		||||
import com.google.gerrit.server.util.SystemLog;
 | 
			
		||||
import com.google.gerrit.testing.FakeEmailSender;
 | 
			
		||||
import com.google.gerrit.testing.FakeGroupAuditService;
 | 
			
		||||
import com.google.gerrit.testing.InMemoryDatabase;
 | 
			
		||||
import com.google.gerrit.testing.InMemoryRepositoryManager;
 | 
			
		||||
import com.google.gerrit.testing.NoteDbChecker;
 | 
			
		||||
@@ -355,6 +356,7 @@ public class GerritServer implements AutoCloseable {
 | 
			
		||||
            },
 | 
			
		||||
            site);
 | 
			
		||||
    daemon.setEmailModuleForTesting(new FakeEmailSender.Module());
 | 
			
		||||
    daemon.setAuditEventModuleForTesting(new FakeGroupAuditService.Module());
 | 
			
		||||
    daemon.setAdditionalSysModuleForTesting(testSysModule);
 | 
			
		||||
    daemon.setEnableSshd(desc.useSsh());
 | 
			
		||||
    daemon.setSlave(isSlave(baseConfig));
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ import java.lang.annotation.Target;
 | 
			
		||||
 * Audit annotation for JSON/RPC interfaces.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>Flag with @Audit all the JSON/RPC methods to be traced in audit-trail and submitted to the
 | 
			
		||||
 * AuditService.
 | 
			
		||||
 * GroupAuditService.
 | 
			
		||||
 */
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Target({ElementType.METHOD})
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,8 @@
 | 
			
		||||
package com.google.gerrit.httpd;
 | 
			
		||||
 | 
			
		||||
import com.google.common.cache.Cache;
 | 
			
		||||
import com.google.common.collect.ArrayListMultimap;
 | 
			
		||||
import com.google.common.collect.ListMultimap;
 | 
			
		||||
import com.google.common.collect.Lists;
 | 
			
		||||
import com.google.gerrit.common.data.Capable;
 | 
			
		||||
import com.google.gerrit.extensions.registration.DynamicSet;
 | 
			
		||||
@@ -23,6 +25,7 @@ import com.google.gerrit.reviewdb.client.Project;
 | 
			
		||||
import com.google.gerrit.server.AccessPath;
 | 
			
		||||
import com.google.gerrit.server.AnonymousUser;
 | 
			
		||||
import com.google.gerrit.server.CurrentUser;
 | 
			
		||||
import com.google.gerrit.server.audit.HttpAuditEvent;
 | 
			
		||||
import com.google.gerrit.server.cache.CacheModule;
 | 
			
		||||
import com.google.gerrit.server.git.DefaultAdvertiseRefsHook;
 | 
			
		||||
import com.google.gerrit.server.git.GitRepositoryManager;
 | 
			
		||||
@@ -30,12 +33,14 @@ 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.permissions.PermissionBackend;
 | 
			
		||||
import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
 | 
			
		||||
import com.google.gerrit.server.permissions.PermissionBackendException;
 | 
			
		||||
import com.google.gerrit.server.permissions.ProjectPermission;
 | 
			
		||||
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;
 | 
			
		||||
@@ -44,6 +49,7 @@ 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.Set;
 | 
			
		||||
@@ -141,6 +147,30 @@ public class GitOverHttpServlet extends GitServlet {
 | 
			
		||||
    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) {
 | 
			
		||||
 | 
			
		||||
    ListMultimap<String, String> multiMap = ArrayListMultimap.create();
 | 
			
		||||
    if (request.getQueryString() != null) {
 | 
			
		||||
      request
 | 
			
		||||
          .getParameterMap()
 | 
			
		||||
          .forEach(
 | 
			
		||||
              (k, v) -> {
 | 
			
		||||
                for (int i = 0; i < v.length; i++) {
 | 
			
		||||
                  multiMap.put(k, v[i]);
 | 
			
		||||
                }
 | 
			
		||||
              });
 | 
			
		||||
    }
 | 
			
		||||
    return multiMap;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static class Resolver implements RepositoryResolver<HttpServletRequest> {
 | 
			
		||||
    private final GitRepositoryManager manager;
 | 
			
		||||
    private final PermissionBackend permissionBackend;
 | 
			
		||||
@@ -229,6 +259,13 @@ public class GitOverHttpServlet extends GitServlet {
 | 
			
		||||
      up.setTimeout(config.getTimeout());
 | 
			
		||||
      up.setPreUploadHook(PreUploadHookChain.newChain(Lists.newArrayList(preUploadHooks)));
 | 
			
		||||
      up.setPostUploadHook(PostUploadHookChain.newChain(Lists.newArrayList(postUploadHooks)));
 | 
			
		||||
      if (config.enableProtocolV2()) {
 | 
			
		||||
        String header = req.getHeader("Git-Protocol");
 | 
			
		||||
        if (header != null) {
 | 
			
		||||
          String[] params = header.split(":");
 | 
			
		||||
          up.setExtraParameters(Arrays.asList(params));
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      ProjectState state = (ProjectState) req.getAttribute(ATT_STATE);
 | 
			
		||||
      for (UploadPackInitializer initializer : uploadPackInitializers) {
 | 
			
		||||
        initializer.init(state.getNameKey(), up);
 | 
			
		||||
@@ -240,12 +277,19 @@ public class GitOverHttpServlet extends GitServlet {
 | 
			
		||||
  static class UploadFilter implements Filter {
 | 
			
		||||
    private final UploadValidators.Factory uploadValidatorsFactory;
 | 
			
		||||
    private final PermissionBackend permissionBackend;
 | 
			
		||||
    private final Provider<CurrentUser> userProvider;
 | 
			
		||||
    private final GroupAuditService groupAuditService;
 | 
			
		||||
 | 
			
		||||
    @Inject
 | 
			
		||||
    UploadFilter(
 | 
			
		||||
        UploadValidators.Factory uploadValidatorsFactory, PermissionBackend permissionBackend) {
 | 
			
		||||
        UploadValidators.Factory uploadValidatorsFactory,
 | 
			
		||||
        PermissionBackend permissionBackend,
 | 
			
		||||
        Provider<CurrentUser> userProvider,
 | 
			
		||||
        GroupAuditService groupAuditService) {
 | 
			
		||||
      this.uploadValidatorsFactory = uploadValidatorsFactory;
 | 
			
		||||
      this.permissionBackend = permissionBackend;
 | 
			
		||||
      this.userProvider = userProvider;
 | 
			
		||||
      this.groupAuditService = groupAuditService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -268,7 +312,22 @@ public class GitOverHttpServlet extends GitServlet {
 | 
			
		||||
        return;
 | 
			
		||||
      } catch (PermissionBackendException e) {
 | 
			
		||||
        throw new ServletException(e);
 | 
			
		||||
      } finally {
 | 
			
		||||
        HttpServletRequest httpRequest = (HttpServletRequest) request;
 | 
			
		||||
        HttpServletResponse httpResponse = (HttpServletResponse) response;
 | 
			
		||||
        groupAuditService.dispatch(
 | 
			
		||||
            new HttpAuditEvent(
 | 
			
		||||
                httpRequest.getSession().getId(),
 | 
			
		||||
                userProvider.get(),
 | 
			
		||||
                extractWhat(httpRequest),
 | 
			
		||||
                TimeUtil.nowMs(),
 | 
			
		||||
                extractParameters(httpRequest),
 | 
			
		||||
                httpRequest.getMethod(),
 | 
			
		||||
                httpRequest,
 | 
			
		||||
                httpResponse.getStatus(),
 | 
			
		||||
                httpResponse));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // 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 =
 | 
			
		||||
@@ -326,15 +385,18 @@ public class GitOverHttpServlet extends GitServlet {
 | 
			
		||||
    private final Cache<AdvertisedObjectsCacheKey, Set<ObjectId>> cache;
 | 
			
		||||
    private final PermissionBackend permissionBackend;
 | 
			
		||||
    private final Provider<CurrentUser> userProvider;
 | 
			
		||||
    private final GroupAuditService groupAuditService;
 | 
			
		||||
 | 
			
		||||
    @Inject
 | 
			
		||||
    ReceiveFilter(
 | 
			
		||||
        @Named(ID_CACHE) Cache<AdvertisedObjectsCacheKey, Set<ObjectId>> cache,
 | 
			
		||||
        PermissionBackend permissionBackend,
 | 
			
		||||
        Provider<CurrentUser> userProvider) {
 | 
			
		||||
        Provider<CurrentUser> userProvider,
 | 
			
		||||
        GroupAuditService groupAuditService) {
 | 
			
		||||
      this.cache = cache;
 | 
			
		||||
      this.permissionBackend = permissionBackend;
 | 
			
		||||
      this.userProvider = userProvider;
 | 
			
		||||
      this.groupAuditService = groupAuditService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -365,6 +427,20 @@ public class GitOverHttpServlet extends GitServlet {
 | 
			
		||||
        return;
 | 
			
		||||
      } catch (PermissionBackendException e) {
 | 
			
		||||
        throw new RuntimeException(e);
 | 
			
		||||
      } finally {
 | 
			
		||||
        HttpServletRequest httpRequest = (HttpServletRequest) request;
 | 
			
		||||
        HttpServletResponse httpResponse = (HttpServletResponse) response;
 | 
			
		||||
        groupAuditService.dispatch(
 | 
			
		||||
            new HttpAuditEvent(
 | 
			
		||||
                httpRequest.getSession().getId(),
 | 
			
		||||
                userProvider.get(),
 | 
			
		||||
                extractWhat(httpRequest),
 | 
			
		||||
                TimeUtil.nowMs(),
 | 
			
		||||
                extractParameters(httpRequest),
 | 
			
		||||
                httpRequest.getMethod(),
 | 
			
		||||
                httpRequest,
 | 
			
		||||
                httpResponse.getStatus(),
 | 
			
		||||
                httpResponse));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (canUpload != Capable.OK) {
 | 
			
		||||
 
 | 
			
		||||
@@ -17,8 +17,8 @@ package com.google.gerrit.httpd;
 | 
			
		||||
import com.google.common.base.Strings;
 | 
			
		||||
import com.google.gerrit.common.Nullable;
 | 
			
		||||
import com.google.gerrit.extensions.registration.DynamicItem;
 | 
			
		||||
import com.google.gerrit.server.AuditEvent;
 | 
			
		||||
import com.google.gerrit.server.CurrentUser;
 | 
			
		||||
import com.google.gerrit.server.audit.AuditEvent;
 | 
			
		||||
import com.google.gerrit.server.audit.AuditService;
 | 
			
		||||
import com.google.gerrit.server.config.AuthConfig;
 | 
			
		||||
import com.google.gerrit.server.config.CanonicalWebUrl;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,19 +14,17 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.httpd.init;
 | 
			
		||||
 | 
			
		||||
import com.google.common.base.Strings;
 | 
			
		||||
import com.google.common.flogger.FluentLogger;
 | 
			
		||||
import com.google.gerrit.pgm.init.BaseInit;
 | 
			
		||||
import com.google.gerrit.pgm.init.PluginsDistribution;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
import java.nio.file.Paths;
 | 
			
		||||
import java.sql.Connection;
 | 
			
		||||
import java.sql.ResultSet;
 | 
			
		||||
import java.sql.SQLException;
 | 
			
		||||
import java.sql.Statement;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public final class SiteInitializer {
 | 
			
		||||
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 | 
			
		||||
  private static final String GERRIT_SITE_PATH = "gerrit.site_path";
 | 
			
		||||
 | 
			
		||||
  private final String sitePath;
 | 
			
		||||
  private final String initPath;
 | 
			
		||||
@@ -53,8 +51,12 @@ public final class SiteInitializer {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      try (Connection conn = connectToDb()) {
 | 
			
		||||
        Path site = getSiteFromReviewDb(conn);
 | 
			
		||||
      String path = System.getProperty(GERRIT_SITE_PATH);
 | 
			
		||||
      Path site = null;
 | 
			
		||||
      if (!Strings.isNullOrEmpty(path)) {
 | 
			
		||||
        site = Paths.get(path);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (site == null && initPath != null) {
 | 
			
		||||
        site = Paths.get(initPath);
 | 
			
		||||
      }
 | 
			
		||||
@@ -69,26 +71,9 @@ public final class SiteInitializer {
 | 
			
		||||
                pluginsToInstall)
 | 
			
		||||
            .run();
 | 
			
		||||
      }
 | 
			
		||||
      }
 | 
			
		||||
    } catch (Exception e) {
 | 
			
		||||
      logger.atSevere().withCause(e).log("Site init failed");
 | 
			
		||||
      throw new RuntimeException(e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private Connection connectToDb() throws SQLException {
 | 
			
		||||
    return new ReviewDbDataSourceProvider().get().getConnection();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private Path getSiteFromReviewDb(Connection conn) {
 | 
			
		||||
    try (Statement stmt = conn.createStatement();
 | 
			
		||||
        ResultSet rs = stmt.executeQuery("SELECT site_path FROM system_config")) {
 | 
			
		||||
      if (rs.next()) {
 | 
			
		||||
        return Paths.get(rs.getString(1));
 | 
			
		||||
      }
 | 
			
		||||
    } catch (SQLException e) {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,58 +0,0 @@
 | 
			
		||||
// 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.httpd.init;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.reviewdb.client.SystemConfig;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.server.config.SitePath;
 | 
			
		||||
import com.google.gerrit.server.schema.ReviewDbFactory;
 | 
			
		||||
import com.google.gwtorm.server.OrmException;
 | 
			
		||||
import com.google.gwtorm.server.SchemaFactory;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
import java.nio.file.Paths;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/** Provides {@link Path} annotated with {@link SitePath}. */
 | 
			
		||||
class SitePathFromSystemConfigProvider implements Provider<Path> {
 | 
			
		||||
  private final Path path;
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  SitePathFromSystemConfigProvider(@ReviewDbFactory SchemaFactory<ReviewDb> schemaFactory)
 | 
			
		||||
      throws OrmException {
 | 
			
		||||
    path = read(schemaFactory);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Path get() {
 | 
			
		||||
    return path;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static Path read(SchemaFactory<ReviewDb> schemaFactory) throws OrmException {
 | 
			
		||||
    try (ReviewDb db = schemaFactory.open()) {
 | 
			
		||||
      List<SystemConfig> all = db.systemConfig().all().toList();
 | 
			
		||||
      switch (all.size()) {
 | 
			
		||||
        case 1:
 | 
			
		||||
          return Paths.get(all.get(0).sitePath);
 | 
			
		||||
        case 0:
 | 
			
		||||
          throw new OrmException("system_config table is empty");
 | 
			
		||||
        default:
 | 
			
		||||
          throw new OrmException(
 | 
			
		||||
              "system_config must have exactly 1 row; found " + all.size() + " rows instead");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -48,6 +48,7 @@ import com.google.gerrit.server.StartupChecks;
 | 
			
		||||
import com.google.gerrit.server.account.AccountDeactivator;
 | 
			
		||||
import com.google.gerrit.server.account.InternalAccountDirectory;
 | 
			
		||||
import com.google.gerrit.server.api.GerritApiModule;
 | 
			
		||||
import com.google.gerrit.server.api.PluginApiModule;
 | 
			
		||||
import com.google.gerrit.server.audit.AuditModule;
 | 
			
		||||
import com.google.gerrit.server.cache.h2.H2CacheModule;
 | 
			
		||||
import com.google.gerrit.server.cache.mem.DefaultMemoryCacheModule;
 | 
			
		||||
@@ -60,6 +61,7 @@ import com.google.gerrit.server.config.DownloadConfig;
 | 
			
		||||
import com.google.gerrit.server.config.GerritGlobalModule;
 | 
			
		||||
import com.google.gerrit.server.config.GerritInstanceNameModule;
 | 
			
		||||
import com.google.gerrit.server.config.GerritOptions;
 | 
			
		||||
import com.google.gerrit.server.config.GerritRuntime;
 | 
			
		||||
import com.google.gerrit.server.config.GerritServerConfig;
 | 
			
		||||
import com.google.gerrit.server.config.GerritServerConfigModule;
 | 
			
		||||
import com.google.gerrit.server.config.SitePath;
 | 
			
		||||
@@ -107,6 +109,7 @@ import com.google.inject.Injector;
 | 
			
		||||
import com.google.inject.Key;
 | 
			
		||||
import com.google.inject.Module;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
import com.google.inject.ProvisionException;
 | 
			
		||||
import com.google.inject.name.Names;
 | 
			
		||||
import com.google.inject.servlet.GuiceFilter;
 | 
			
		||||
import com.google.inject.servlet.GuiceServletContextListener;
 | 
			
		||||
@@ -134,6 +137,8 @@ import org.eclipse.jgit.lib.Config;
 | 
			
		||||
public class WebAppInitializer extends GuiceServletContextListener implements Filter {
 | 
			
		||||
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 | 
			
		||||
 | 
			
		||||
  private static final String GERRIT_SITE_PATH = "gerrit.site_path";
 | 
			
		||||
 | 
			
		||||
  private Path sitePath;
 | 
			
		||||
  private Injector dbInjector;
 | 
			
		||||
  private Injector cfgInjector;
 | 
			
		||||
@@ -155,9 +160,11 @@ public class WebAppInitializer extends GuiceServletContextListener implements Fi
 | 
			
		||||
 | 
			
		||||
  private synchronized void init() {
 | 
			
		||||
    if (manager == null) {
 | 
			
		||||
      final String path = System.getProperty("gerrit.site_path");
 | 
			
		||||
      String path = System.getProperty(GERRIT_SITE_PATH);
 | 
			
		||||
      if (path != null) {
 | 
			
		||||
        sitePath = Paths.get(path);
 | 
			
		||||
      } else {
 | 
			
		||||
        throw new ProvisionException(GERRIT_SITE_PATH + " must be defined");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (System.getProperty("gerrit.init") != null) {
 | 
			
		||||
@@ -171,7 +178,7 @@ public class WebAppInitializer extends GuiceServletContextListener implements Fi
 | 
			
		||||
        }
 | 
			
		||||
        new SiteInitializer(
 | 
			
		||||
                path,
 | 
			
		||||
                System.getProperty("gerrit.init_path"),
 | 
			
		||||
                System.getProperty(GERRIT_SITE_PATH),
 | 
			
		||||
                new UnzippedDistribution(servletContext),
 | 
			
		||||
                pluginsToInstall)
 | 
			
		||||
            .init();
 | 
			
		||||
@@ -292,21 +299,6 @@ public class WebAppInitializer extends GuiceServletContextListener implements Fi
 | 
			
		||||
              listener().to(ReviewDbDataSourceProvider.class);
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
      // If we didn't get the site path from the system property
 | 
			
		||||
      // we need to get it from the database, as that's our old
 | 
			
		||||
      // method of locating the site path on disk.
 | 
			
		||||
      //
 | 
			
		||||
      modules.add(
 | 
			
		||||
          new AbstractModule() {
 | 
			
		||||
            @Override
 | 
			
		||||
            protected void configure() {
 | 
			
		||||
              bind(Path.class)
 | 
			
		||||
                  .annotatedWith(SitePath.class)
 | 
			
		||||
                  .toProvider(SitePathFromSystemConfigProvider.class)
 | 
			
		||||
                  .in(SINGLETON);
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
      modules.add(new GerritServerConfigModule());
 | 
			
		||||
    }
 | 
			
		||||
    modules.add(new DatabaseModule());
 | 
			
		||||
@@ -336,6 +328,7 @@ public class WebAppInitializer extends GuiceServletContextListener implements Fi
 | 
			
		||||
    modules.add(new MimeUtil2Module());
 | 
			
		||||
    modules.add(cfgInjector.getInstance(GerritGlobalModule.class));
 | 
			
		||||
    modules.add(new GerritApiModule());
 | 
			
		||||
    modules.add(new PluginApiModule());
 | 
			
		||||
    modules.add(new SearchingChangeCacheImpl.Module());
 | 
			
		||||
    modules.add(new InternalAccountDirectory.Module());
 | 
			
		||||
    modules.add(new DefaultPermissionBackendModule());
 | 
			
		||||
@@ -385,6 +378,7 @@ public class WebAppInitializer extends GuiceServletContextListener implements Fi
 | 
			
		||||
          @Override
 | 
			
		||||
          protected void configure() {
 | 
			
		||||
            bind(GerritOptions.class).toInstance(new GerritOptions(false, false, false));
 | 
			
		||||
            bind(GerritRuntime.class).toInstance(GerritRuntime.DAEMON);
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
    modules.add(new GarbageCollectionModule());
 | 
			
		||||
 
 | 
			
		||||
@@ -199,6 +199,7 @@ public class Daemon extends SiteProgram {
 | 
			
		||||
  private AbstractModule luceneModule;
 | 
			
		||||
  private Module emailModule;
 | 
			
		||||
  private Module testSysModule;
 | 
			
		||||
  private Module auditEventModule;
 | 
			
		||||
 | 
			
		||||
  private Runnable serverStarted;
 | 
			
		||||
  private IndexType indexType;
 | 
			
		||||
@@ -319,6 +320,11 @@ public class Daemon extends SiteProgram {
 | 
			
		||||
    emailModule = module;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @VisibleForTesting
 | 
			
		||||
  public void setAuditEventModuleForTesting(Module module) {
 | 
			
		||||
    auditEventModule = module;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @VisibleForTesting
 | 
			
		||||
  public void setLuceneModule(LuceneIndexModule m) {
 | 
			
		||||
    luceneModule = m;
 | 
			
		||||
@@ -425,7 +431,6 @@ public class Daemon extends SiteProgram {
 | 
			
		||||
    modules.add(cfgInjector.getInstance(GerritGlobalModule.class));
 | 
			
		||||
    modules.add(new GerritApiModule());
 | 
			
		||||
    modules.add(new PluginApiModule());
 | 
			
		||||
    modules.add(new AuditModule());
 | 
			
		||||
 | 
			
		||||
    modules.add(new SearchingChangeCacheImpl.Module(slave));
 | 
			
		||||
    modules.add(new InternalAccountDirectory.Module());
 | 
			
		||||
@@ -438,6 +443,11 @@ public class Daemon extends SiteProgram {
 | 
			
		||||
    } else {
 | 
			
		||||
      modules.add(new SmtpEmailSender.Module());
 | 
			
		||||
    }
 | 
			
		||||
    if (auditEventModule != null) {
 | 
			
		||||
      modules.add(auditEventModule);
 | 
			
		||||
    } else {
 | 
			
		||||
      modules.add(new AuditModule());
 | 
			
		||||
    }
 | 
			
		||||
    modules.add(new SignedTokenEmailTokenVerifier.Module());
 | 
			
		||||
    modules.add(new RestApiModule());
 | 
			
		||||
    modules.add(new GpgModule(config));
 | 
			
		||||
 
 | 
			
		||||
@@ -1,89 +0,0 @@
 | 
			
		||||
// 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.reviewdb.client;
 | 
			
		||||
 | 
			
		||||
import com.google.gwtorm.client.Column;
 | 
			
		||||
import com.google.gwtorm.client.StringKey;
 | 
			
		||||
 | 
			
		||||
/** Global configuration needed to serve web requests. */
 | 
			
		||||
public final class SystemConfig {
 | 
			
		||||
  public static final class Key extends StringKey<com.google.gwtorm.client.Key<?>> {
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
    private static final String VALUE = "X";
 | 
			
		||||
 | 
			
		||||
    @Column(id = 1, length = 1)
 | 
			
		||||
    protected String one = VALUE;
 | 
			
		||||
 | 
			
		||||
    public Key() {}
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String get() {
 | 
			
		||||
      return VALUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void set(String newValue) {
 | 
			
		||||
      assert get().equals(newValue);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Construct a new, unconfigured instance. */
 | 
			
		||||
  public static SystemConfig create() {
 | 
			
		||||
    final SystemConfig r = new SystemConfig();
 | 
			
		||||
    r.singleton = new SystemConfig.Key();
 | 
			
		||||
    return r;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Column(id = 1)
 | 
			
		||||
  protected Key singleton;
 | 
			
		||||
 | 
			
		||||
  /** Local filesystem location of header/footer/CSS configuration files */
 | 
			
		||||
  @Column(id = 3, notNull = false, length = Integer.MAX_VALUE)
 | 
			
		||||
  public transient String sitePath;
 | 
			
		||||
 | 
			
		||||
  // DO NOT LOOK BELOW THIS LINE. These fields have all been deleted,
 | 
			
		||||
  // but survive to support schema upgrade code.
 | 
			
		||||
 | 
			
		||||
  /** DEPRECATED DO NOT USE */
 | 
			
		||||
  @Column(id = 2, length = 36, notNull = false)
 | 
			
		||||
  public transient String registerEmailPrivateKey;
 | 
			
		||||
  /** DEPRECATED DO NOT USE */
 | 
			
		||||
  @Column(id = 4, notNull = false)
 | 
			
		||||
  public AccountGroup.Id adminGroupId;
 | 
			
		||||
  /** DEPRECATED DO NOT USE */
 | 
			
		||||
  @Column(id = 10, notNull = false)
 | 
			
		||||
  public AccountGroup.UUID adminGroupUUID;
 | 
			
		||||
  /** DEPRECATED DO NOT USE */
 | 
			
		||||
  @Column(id = 5, notNull = false)
 | 
			
		||||
  public AccountGroup.Id anonymousGroupId;
 | 
			
		||||
  /** DEPRECATED DO NOT USE */
 | 
			
		||||
  @Column(id = 6, notNull = false)
 | 
			
		||||
  public AccountGroup.Id registeredGroupId;
 | 
			
		||||
  /** DEPRECATED DO NOT USE */
 | 
			
		||||
  @Column(id = 7, notNull = false)
 | 
			
		||||
  public Project.NameKey wildProjectName;
 | 
			
		||||
  /** DEPRECATED DO NOT USE */
 | 
			
		||||
  @Column(id = 9, notNull = false)
 | 
			
		||||
  public AccountGroup.Id ownerGroupId;
 | 
			
		||||
  /** DEPRECATED DO NOT USE */
 | 
			
		||||
  @Column(id = 8, notNull = false)
 | 
			
		||||
  public AccountGroup.Id batchUsersGroupId;
 | 
			
		||||
  /** DEPRECATED DO NOT USE */
 | 
			
		||||
  @Column(id = 11, notNull = false)
 | 
			
		||||
  public AccountGroup.UUID batchUsersGroupUUID;
 | 
			
		||||
 | 
			
		||||
  protected SystemConfig() {}
 | 
			
		||||
}
 | 
			
		||||
@@ -17,7 +17,6 @@ package com.google.gerrit.reviewdb.server;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Account;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.AccountGroup;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Change;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.SystemConfig;
 | 
			
		||||
import com.google.gwtorm.server.OrmException;
 | 
			
		||||
import com.google.gwtorm.server.Relation;
 | 
			
		||||
import com.google.gwtorm.server.Schema;
 | 
			
		||||
@@ -31,7 +30,6 @@ import com.google.gwtorm.server.Sequence;
 | 
			
		||||
 * <ul>
 | 
			
		||||
 *   <li>{@link Account}: Per-user account registration, preferences, identity.
 | 
			
		||||
 *   <li>{@link Change}: All review information about a single proposed change.
 | 
			
		||||
 *   <li>{@link SystemConfig}: Server-wide settings, managed by administrator.
 | 
			
		||||
 * </ul>
 | 
			
		||||
 */
 | 
			
		||||
public interface ReviewDb extends Schema {
 | 
			
		||||
@@ -40,8 +38,7 @@ public interface ReviewDb extends Schema {
 | 
			
		||||
  @Relation(id = 1)
 | 
			
		||||
  SchemaVersionAccess schemaVersion();
 | 
			
		||||
 | 
			
		||||
  @Relation(id = 2)
 | 
			
		||||
  SystemConfigAccess systemConfig();
 | 
			
		||||
  // Deleted @Relation(id = 2)
 | 
			
		||||
 | 
			
		||||
  // Deleted @Relation(id = 3)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -109,11 +109,6 @@ public class ReviewDbWrapper implements ReviewDb {
 | 
			
		||||
    return delegate.schemaVersion();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public SystemConfigAccess systemConfig() {
 | 
			
		||||
    return delegate.systemConfig();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public ChangeAccess changes() {
 | 
			
		||||
    return delegate.changes();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,32 +0,0 @@
 | 
			
		||||
// 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.reviewdb.server;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.reviewdb.client.SystemConfig;
 | 
			
		||||
import com.google.gwtorm.server.Access;
 | 
			
		||||
import com.google.gwtorm.server.OrmException;
 | 
			
		||||
import com.google.gwtorm.server.PrimaryKey;
 | 
			
		||||
import com.google.gwtorm.server.Query;
 | 
			
		||||
import com.google.gwtorm.server.ResultSet;
 | 
			
		||||
 | 
			
		||||
/** Access interface for {@link SystemConfig}. */
 | 
			
		||||
public interface SystemConfigAccess extends Access<SystemConfig, SystemConfig.Key> {
 | 
			
		||||
  @Override
 | 
			
		||||
  @PrimaryKey("singleton")
 | 
			
		||||
  SystemConfig get(SystemConfig.Key key) throws OrmException;
 | 
			
		||||
 | 
			
		||||
  @Query
 | 
			
		||||
  ResultSet<SystemConfig> all() throws OrmException;
 | 
			
		||||
}
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.server.audit;
 | 
			
		||||
package com.google.gerrit.server;
 | 
			
		||||
 | 
			
		||||
import static java.util.Objects.requireNonNull;
 | 
			
		||||
 | 
			
		||||
@@ -20,7 +20,6 @@ import com.google.auto.value.AutoValue;
 | 
			
		||||
import com.google.common.base.MoreObjects;
 | 
			
		||||
import com.google.common.collect.ImmutableListMultimap;
 | 
			
		||||
import com.google.common.collect.ListMultimap;
 | 
			
		||||
import com.google.gerrit.server.CurrentUser;
 | 
			
		||||
import com.google.gerrit.server.util.time.TimeUtil;
 | 
			
		||||
 | 
			
		||||
public class AuditEvent {
 | 
			
		||||
@@ -15,6 +15,7 @@
 | 
			
		||||
package com.google.gerrit.server.audit;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.extensions.annotations.ExtensionPoint;
 | 
			
		||||
import com.google.gerrit.server.AuditEvent;
 | 
			
		||||
 | 
			
		||||
@ExtensionPoint
 | 
			
		||||
public interface AuditListener {
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ package com.google.gerrit.server.audit;
 | 
			
		||||
import com.google.common.collect.ImmutableSet;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Account;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.AccountGroup;
 | 
			
		||||
import com.google.gerrit.server.AuditEvent;
 | 
			
		||||
import com.google.gerrit.server.audit.group.GroupAuditListener;
 | 
			
		||||
import com.google.gerrit.server.audit.group.GroupMemberAuditEvent;
 | 
			
		||||
import com.google.gerrit.server.audit.group.GroupSubgroupAuditEvent;
 | 
			
		||||
@@ -39,6 +40,7 @@ public class AuditService implements GroupAuditService {
 | 
			
		||||
    this.groupAuditListeners = groupAuditListeners;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void dispatch(AuditEvent action) {
 | 
			
		||||
    auditListeners.runEach(l -> l.onAuditableAction(action));
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
package com.google.gerrit.server.audit;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ListMultimap;
 | 
			
		||||
import com.google.gerrit.server.AuditEvent;
 | 
			
		||||
import com.google.gerrit.server.CurrentUser;
 | 
			
		||||
 | 
			
		||||
public class HttpAuditEvent extends AuditEvent {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@
 | 
			
		||||
package com.google.gerrit.server.audit;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ListMultimap;
 | 
			
		||||
import com.google.gerrit.server.AuditEvent;
 | 
			
		||||
import com.google.gerrit.server.CurrentUser;
 | 
			
		||||
 | 
			
		||||
public class SshAuditEvent extends AuditEvent {
 | 
			
		||||
 
 | 
			
		||||
@@ -13,10 +13,11 @@
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
package com.google.gerrit.server.config;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ImmutableList;
 | 
			
		||||
import com.google.common.collect.ArrayListMultimap;
 | 
			
		||||
import com.google.common.collect.ImmutableMultimap;
 | 
			
		||||
import com.google.common.collect.Multimap;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.LinkedHashSet;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import org.apache.commons.lang.StringUtils;
 | 
			
		||||
@@ -36,6 +37,8 @@ import org.eclipse.jgit.lib.Config;
 | 
			
		||||
 * (+ various overloaded versions of these)
 | 
			
		||||
 */
 | 
			
		||||
public class ConfigUpdatedEvent {
 | 
			
		||||
  public static final Multimap<UpdateResult, ConfigUpdateEntry> NO_UPDATES =
 | 
			
		||||
      new ImmutableMultimap.Builder<UpdateResult, ConfigUpdateEntry>().build();
 | 
			
		||||
  private final Config oldConfig;
 | 
			
		||||
  private final Config newConfig;
 | 
			
		||||
 | 
			
		||||
@@ -52,25 +55,29 @@ public class ConfigUpdatedEvent {
 | 
			
		||||
    return this.newConfig;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public Update accept(ConfigKey entry) {
 | 
			
		||||
  private String getString(ConfigKey key, Config config) {
 | 
			
		||||
    return config.getString(key.section(), key.subsection(), key.name());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public Multimap<UpdateResult, ConfigUpdateEntry> accept(ConfigKey entry) {
 | 
			
		||||
    return accept(Collections.singleton(entry));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public Update accept(Set<ConfigKey> entries) {
 | 
			
		||||
  public Multimap<UpdateResult, ConfigUpdateEntry> accept(Set<ConfigKey> entries) {
 | 
			
		||||
    return createUpdate(entries, UpdateResult.APPLIED);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public Update accept(String section) {
 | 
			
		||||
  public Multimap<UpdateResult, ConfigUpdateEntry> accept(String section) {
 | 
			
		||||
    Set<ConfigKey> entries = getEntriesFromSection(oldConfig, section);
 | 
			
		||||
    entries.addAll(getEntriesFromSection(newConfig, section));
 | 
			
		||||
    return createUpdate(entries, UpdateResult.APPLIED);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public Update reject(ConfigKey entry) {
 | 
			
		||||
  public Multimap<UpdateResult, ConfigUpdateEntry> reject(ConfigKey entry) {
 | 
			
		||||
    return reject(Collections.singleton(entry));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public Update reject(Set<ConfigKey> entries) {
 | 
			
		||||
  public Multimap<UpdateResult, ConfigUpdateEntry> reject(Set<ConfigKey> entries) {
 | 
			
		||||
    return createUpdate(entries, UpdateResult.REJECTED);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -87,20 +94,15 @@ public class ConfigUpdatedEvent {
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private Update createUpdate(Set<ConfigKey> entries, UpdateResult updateResult) {
 | 
			
		||||
    Update update = new Update(updateResult);
 | 
			
		||||
  private Multimap<UpdateResult, ConfigUpdateEntry> createUpdate(
 | 
			
		||||
      Set<ConfigKey> entries, UpdateResult updateResult) {
 | 
			
		||||
    Multimap<UpdateResult, ConfigUpdateEntry> updates = ArrayListMultimap.create();
 | 
			
		||||
    entries
 | 
			
		||||
        .stream()
 | 
			
		||||
        .filter(this::isValueUpdated)
 | 
			
		||||
        .forEach(
 | 
			
		||||
            key -> {
 | 
			
		||||
              update.addConfigUpdate(
 | 
			
		||||
                  new ConfigUpdateEntry(
 | 
			
		||||
                      key,
 | 
			
		||||
                      oldConfig.getString(key.section(), key.subsection(), key.name()),
 | 
			
		||||
                      newConfig.getString(key.section(), key.subsection(), key.name())));
 | 
			
		||||
            });
 | 
			
		||||
    return update;
 | 
			
		||||
        .map(e -> new ConfigUpdateEntry(e, getString(e, oldConfig), getString(e, newConfig)))
 | 
			
		||||
        .forEach(e -> updates.put(updateResult, e));
 | 
			
		||||
    return updates;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean isSectionUpdated(String section) {
 | 
			
		||||
@@ -142,31 +144,6 @@ public class ConfigUpdatedEvent {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * One Accepted/Rejected Update have one or more config updates (ConfigUpdateEntry) tied to it.
 | 
			
		||||
   */
 | 
			
		||||
  public static class Update {
 | 
			
		||||
    private UpdateResult result;
 | 
			
		||||
    private final Set<ConfigUpdateEntry> configUpdates;
 | 
			
		||||
 | 
			
		||||
    public Update(UpdateResult result) {
 | 
			
		||||
      this.configUpdates = new LinkedHashSet<>();
 | 
			
		||||
      this.result = result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public UpdateResult getResult() {
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public List<ConfigUpdateEntry> getConfigUpdates() {
 | 
			
		||||
      return ImmutableList.copyOf(configUpdates);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void addConfigUpdate(ConfigUpdateEntry entry) {
 | 
			
		||||
      this.configUpdates.add(entry);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public enum ConfigEntryType {
 | 
			
		||||
    ADDED,
 | 
			
		||||
    REMOVED,
 | 
			
		||||
 
 | 
			
		||||
@@ -14,9 +14,11 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.server.config;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.Multimap;
 | 
			
		||||
import com.google.gerrit.extensions.annotations.ExtensionPoint;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
 | 
			
		||||
import java.util.EventListener;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implementations of the GerritConfigListener interface expects to react GerritServerConfig
 | 
			
		||||
@@ -24,5 +26,5 @@ import java.util.List;
 | 
			
		||||
 */
 | 
			
		||||
@ExtensionPoint
 | 
			
		||||
public interface GerritConfigListener extends EventListener {
 | 
			
		||||
  List<ConfigUpdatedEvent.Update> configUpdated(ConfigUpdatedEvent event);
 | 
			
		||||
  Multimap<UpdateResult, ConfigUpdateEntry> configUpdated(ConfigUpdatedEvent event);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,13 +15,12 @@
 | 
			
		||||
package com.google.gerrit.server.config;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ImmutableSet;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
 | 
			
		||||
public class GerritConfigListenerHelper {
 | 
			
		||||
  public static GerritConfigListener acceptIfChanged(ConfigKey... keys) {
 | 
			
		||||
    return e ->
 | 
			
		||||
        e.isEntriesUpdated(ImmutableSet.copyOf(keys))
 | 
			
		||||
            ? Collections.singletonList(e.accept(ImmutableSet.copyOf(keys)))
 | 
			
		||||
            : Collections.emptyList();
 | 
			
		||||
            ? e.accept(ImmutableSet.copyOf(keys))
 | 
			
		||||
            : ConfigUpdatedEvent.NO_UPDATES;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,12 +14,14 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.server.config;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ArrayListMultimap;
 | 
			
		||||
import com.google.common.collect.Multimap;
 | 
			
		||||
import com.google.common.flogger.FluentLogger;
 | 
			
		||||
import com.google.gerrit.extensions.registration.DynamicSet;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Singleton;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/** Issues a configuration reload from the GerritServerConfigProvider and notify all listeners. */
 | 
			
		||||
@Singleton
 | 
			
		||||
@@ -40,18 +42,20 @@ public class GerritServerConfigReloader {
 | 
			
		||||
   * Reloads the Gerrit Server Configuration from disk. Synchronized to ensure that one issued
 | 
			
		||||
   * reload is fully completed before a new one starts.
 | 
			
		||||
   */
 | 
			
		||||
  public List<ConfigUpdatedEvent.Update> reloadConfig() {
 | 
			
		||||
  public Multimap<UpdateResult, ConfigUpdateEntry> reloadConfig() {
 | 
			
		||||
    logger.atInfo().log("Starting server configuration reload");
 | 
			
		||||
    List<ConfigUpdatedEvent.Update> updates = fireUpdatedConfigEvent(configProvider.updateConfig());
 | 
			
		||||
    Multimap<UpdateResult, ConfigUpdateEntry> updates =
 | 
			
		||||
        fireUpdatedConfigEvent(configProvider.updateConfig());
 | 
			
		||||
    logger.atInfo().log("Server configuration reload completed succesfully");
 | 
			
		||||
    return updates;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public List<ConfigUpdatedEvent.Update> fireUpdatedConfigEvent(ConfigUpdatedEvent event) {
 | 
			
		||||
    ArrayList<ConfigUpdatedEvent.Update> result = new ArrayList<>();
 | 
			
		||||
  public Multimap<UpdateResult, ConfigUpdateEntry> fireUpdatedConfigEvent(
 | 
			
		||||
      ConfigUpdatedEvent event) {
 | 
			
		||||
    Multimap<UpdateResult, ConfigUpdateEntry> updates = ArrayListMultimap.create();
 | 
			
		||||
    for (GerritConfigListener configListener : configListeners) {
 | 
			
		||||
      result.addAll(configListener.configUpdated(event));
 | 
			
		||||
      updates.putAll(configListener.configUpdated(event));
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
    return updates;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@ public class TransferConfig {
 | 
			
		||||
  private final long maxObjectSizeLimit;
 | 
			
		||||
  private final String maxObjectSizeLimitFormatted;
 | 
			
		||||
  private final boolean inheritProjectMaxObjectSizeLimit;
 | 
			
		||||
  private final boolean enableProtocolV2;
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  TransferConfig(@GerritServerConfig Config cfg) {
 | 
			
		||||
@@ -45,6 +46,7 @@ public class TransferConfig {
 | 
			
		||||
    maxObjectSizeLimitFormatted = cfg.getString("receive", null, "maxObjectSizeLimit");
 | 
			
		||||
    inheritProjectMaxObjectSizeLimit =
 | 
			
		||||
        cfg.getBoolean("receive", "inheritProjectMaxObjectSizeLimit", false);
 | 
			
		||||
    enableProtocolV2 = cfg.getBoolean("receive", "enableProtocolV2", false);
 | 
			
		||||
 | 
			
		||||
    packConfig = new PackConfig();
 | 
			
		||||
    packConfig.setDeltaCompress(false);
 | 
			
		||||
@@ -72,4 +74,8 @@ public class TransferConfig {
 | 
			
		||||
  public boolean inheritProjectMaxObjectSizeLimit() {
 | 
			
		||||
    return inheritProjectMaxObjectSizeLimit;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean enableProtocolV2() {
 | 
			
		||||
    return enableProtocolV2;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,11 @@ import com.google.common.collect.ImmutableSet;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Account;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Account.Id;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.AccountGroup;
 | 
			
		||||
import com.google.gerrit.server.AuditEvent;
 | 
			
		||||
import java.sql.Timestamp;
 | 
			
		||||
 | 
			
		||||
public interface GroupAuditService {
 | 
			
		||||
  void dispatch(AuditEvent action);
 | 
			
		||||
 | 
			
		||||
  void dispatchAddMembers(
 | 
			
		||||
      Account.Id actor,
 | 
			
		||||
 
 | 
			
		||||
@@ -16,15 +16,17 @@ package com.google.gerrit.server.project;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ImmutableList;
 | 
			
		||||
import com.google.common.collect.Lists;
 | 
			
		||||
import com.google.common.collect.Multimap;
 | 
			
		||||
import com.google.common.flogger.FluentLogger;
 | 
			
		||||
import com.google.gerrit.extensions.api.projects.CommentLinkInfo;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
 | 
			
		||||
import com.google.gerrit.server.config.GerritConfigListener;
 | 
			
		||||
import com.google.gerrit.server.config.GerritServerConfig;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
import com.google.inject.Singleton;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import org.eclipse.jgit.lib.Config;
 | 
			
		||||
@@ -64,11 +66,11 @@ public class CommentLinkProvider implements Provider<List<CommentLinkInfo>>, Ger
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public List<ConfigUpdatedEvent.Update> configUpdated(ConfigUpdatedEvent event) {
 | 
			
		||||
  public Multimap<UpdateResult, ConfigUpdateEntry> configUpdated(ConfigUpdatedEvent event) {
 | 
			
		||||
    if (event.isSectionUpdated(ProjectConfig.COMMENTLINK)) {
 | 
			
		||||
      commentLinks = parseConfig(event.getNewConfig());
 | 
			
		||||
      return Collections.singletonList(event.accept(ProjectConfig.COMMENTLINK));
 | 
			
		||||
      return event.accept(ProjectConfig.COMMENTLINK);
 | 
			
		||||
    }
 | 
			
		||||
    return Collections.emptyList();
 | 
			
		||||
    return ConfigUpdatedEvent.NO_UPDATES;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,12 +16,12 @@ package com.google.gerrit.server.restapi.config;
 | 
			
		||||
 | 
			
		||||
import static com.google.common.collect.ImmutableList.toImmutableList;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.Multimap;
 | 
			
		||||
import com.google.gerrit.extensions.api.config.ConfigUpdateEntryInfo;
 | 
			
		||||
import com.google.gerrit.extensions.common.Input;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.RestApiException;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.RestModifyView;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigResource;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
 | 
			
		||||
import com.google.gerrit.server.config.GerritServerConfigReloader;
 | 
			
		||||
@@ -29,10 +29,11 @@ import com.google.gerrit.server.permissions.GlobalPermission;
 | 
			
		||||
import com.google.gerrit.server.permissions.PermissionBackend;
 | 
			
		||||
import com.google.gerrit.server.permissions.PermissionBackendException;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
public class ReloadConfig implements RestModifyView<ConfigResource, Input> {
 | 
			
		||||
 | 
			
		||||
@@ -49,25 +50,22 @@ public class ReloadConfig implements RestModifyView<ConfigResource, Input> {
 | 
			
		||||
  public Map<String, List<ConfigUpdateEntryInfo>> apply(ConfigResource resource, Input input)
 | 
			
		||||
      throws RestApiException, PermissionBackendException {
 | 
			
		||||
    permissions.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
 | 
			
		||||
 | 
			
		||||
    List<ConfigUpdatedEvent.Update> updates = config.reloadConfig();
 | 
			
		||||
 | 
			
		||||
    Map<String, List<ConfigUpdateEntryInfo>> reply = new HashMap<>();
 | 
			
		||||
    for (UpdateResult result : UpdateResult.values()) {
 | 
			
		||||
      reply.put(result.name().toLowerCase(), new ArrayList<>());
 | 
			
		||||
    }
 | 
			
		||||
    Multimap<UpdateResult, ConfigUpdateEntry> updates = config.reloadConfig();
 | 
			
		||||
    if (updates.isEmpty()) {
 | 
			
		||||
      return reply;
 | 
			
		||||
      return Collections.emptyMap();
 | 
			
		||||
    }
 | 
			
		||||
    updates
 | 
			
		||||
    return updates
 | 
			
		||||
        .asMap()
 | 
			
		||||
        .entrySet()
 | 
			
		||||
        .stream()
 | 
			
		||||
        .forEach(u -> reply.get(u.getResult().name().toLowerCase()).addAll(toEntryInfos(u)));
 | 
			
		||||
    return reply;
 | 
			
		||||
        .collect(
 | 
			
		||||
            Collectors.toMap(
 | 
			
		||||
                e -> e.getKey().name().toLowerCase(), e -> toEntryInfos(e.getValue())));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static List<ConfigUpdateEntryInfo> toEntryInfos(ConfigUpdatedEvent.Update update) {
 | 
			
		||||
    return update
 | 
			
		||||
        .getConfigUpdates()
 | 
			
		||||
  private static List<ConfigUpdateEntryInfo> toEntryInfos(
 | 
			
		||||
      Collection<ConfigUpdateEntry> updateEntries) {
 | 
			
		||||
    return updateEntries
 | 
			
		||||
        .stream()
 | 
			
		||||
        .map(ReloadConfig::toConfigUpdateEntryInfo)
 | 
			
		||||
        .collect(toImmutableList());
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ import static java.util.Objects.requireNonNull;
 | 
			
		||||
import com.google.common.base.MoreObjects;
 | 
			
		||||
import com.google.common.base.Strings;
 | 
			
		||||
import com.google.common.collect.Iterables;
 | 
			
		||||
import com.google.common.collect.Multimap;
 | 
			
		||||
import com.google.gerrit.extensions.api.projects.ParentInput;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.AuthException;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.BadRequestException;
 | 
			
		||||
@@ -32,6 +33,8 @@ import com.google.gerrit.server.config.AllProjectsName;
 | 
			
		||||
import com.google.gerrit.server.config.AllUsersName;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigKey;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
 | 
			
		||||
import com.google.gerrit.server.config.GerritConfigListener;
 | 
			
		||||
import com.google.gerrit.server.config.GerritServerConfig;
 | 
			
		||||
import com.google.gerrit.server.git.meta.MetaDataUpdate;
 | 
			
		||||
@@ -46,8 +49,6 @@ import com.google.gerrit.server.project.ProjectState;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Singleton;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import org.eclipse.jgit.errors.ConfigInvalidException;
 | 
			
		||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
 | 
			
		||||
import org.eclipse.jgit.lib.Config;
 | 
			
		||||
@@ -175,18 +176,18 @@ public class SetParent
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public List<ConfigUpdatedEvent.Update> configUpdated(ConfigUpdatedEvent event) {
 | 
			
		||||
  public Multimap<UpdateResult, ConfigUpdateEntry> configUpdated(ConfigUpdatedEvent event) {
 | 
			
		||||
    ConfigKey receiveSetParent = ConfigKey.create("receive", "allowProjectOwnersToChangeParent");
 | 
			
		||||
    if (!event.isValueUpdated(receiveSetParent)) {
 | 
			
		||||
      return Collections.emptyList();
 | 
			
		||||
      return ConfigUpdatedEvent.NO_UPDATES;
 | 
			
		||||
    }
 | 
			
		||||
    try {
 | 
			
		||||
      boolean enabled =
 | 
			
		||||
          event.getNewConfig().getBoolean("receive", "allowProjectOwnersToChangeParent", false);
 | 
			
		||||
      this.allowProjectOwnersToChangeParent = enabled;
 | 
			
		||||
      return Collections.singletonList(event.accept(receiveSetParent));
 | 
			
		||||
    } catch (IllegalArgumentException iae) {
 | 
			
		||||
      return Collections.singletonList(event.reject(receiveSetParent));
 | 
			
		||||
      return event.reject(receiveSetParent);
 | 
			
		||||
    }
 | 
			
		||||
    return event.accept(receiveSetParent);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -275,8 +275,7 @@ class GroupRebuilder {
 | 
			
		||||
   * Distinct event types.
 | 
			
		||||
   *
 | 
			
		||||
   * <p>Events at the same time by the same user are batched together by type. The types should
 | 
			
		||||
   * correspond to the possible batch operations supported by {@link
 | 
			
		||||
   * com.google.gerrit.server.audit.AuditService}.
 | 
			
		||||
   * correspond to the possible batch operations supported by AuditService.
 | 
			
		||||
   */
 | 
			
		||||
  enum Type {
 | 
			
		||||
    ADD_MEMBER,
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,6 @@ import com.google.gerrit.git.RefUpdateUtil;
 | 
			
		||||
import com.google.gerrit.metrics.MetricMaker;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.AccountGroup;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.SystemConfig;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.server.GerritPersonIdent;
 | 
			
		||||
import com.google.gerrit.server.Sequences;
 | 
			
		||||
@@ -150,7 +149,6 @@ public class ReviewDbSchemaCreator {
 | 
			
		||||
    GroupReference admins = createGroupReference("Administrators");
 | 
			
		||||
    GroupReference batchUsers = createGroupReference("Non-Interactive Users");
 | 
			
		||||
 | 
			
		||||
    initSystemConfig(db);
 | 
			
		||||
    allProjectsCreator.setAdministrators(admins).setBatchUsers(batchUsers).create();
 | 
			
		||||
    // We have to create the All-Users repository before we can use it to store the groups in it.
 | 
			
		||||
    allUsersCreator.setAdministrators(admins).create();
 | 
			
		||||
@@ -274,15 +272,4 @@ public class ReviewDbSchemaCreator {
 | 
			
		||||
        .setGroupUUID(groupReference.getUUID())
 | 
			
		||||
        .build();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private SystemConfig initSystemConfig(ReviewDb db) throws OrmException {
 | 
			
		||||
    SystemConfig s = SystemConfig.create();
 | 
			
		||||
    try {
 | 
			
		||||
      s.sitePath = site_path.toRealPath().normalize().toString();
 | 
			
		||||
    } catch (IOException e) {
 | 
			
		||||
      s.sitePath = site_path.toAbsolutePath().normalize().toString();
 | 
			
		||||
    }
 | 
			
		||||
    db.systemConfig().insert(Collections.singleton(s));
 | 
			
		||||
    return s;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,6 @@ package com.google.gerrit.server.schema;
 | 
			
		||||
 | 
			
		||||
import com.google.common.annotations.VisibleForTesting;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.SystemConfig;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDbUtil;
 | 
			
		||||
import com.google.gerrit.server.GerritPersonIdent;
 | 
			
		||||
@@ -38,7 +37,6 @@ import com.google.inject.Provider;
 | 
			
		||||
import com.google.inject.Stage;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.sql.SQLException;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import org.eclipse.jgit.errors.ConfigInvalidException;
 | 
			
		||||
import org.eclipse.jgit.lib.Config;
 | 
			
		||||
import org.eclipse.jgit.lib.PersonIdent;
 | 
			
		||||
@@ -46,18 +44,15 @@ import org.eclipse.jgit.lib.PersonIdent;
 | 
			
		||||
/** Creates or updates the current database schema. */
 | 
			
		||||
public class ReviewDbSchemaUpdater {
 | 
			
		||||
  private final SchemaFactory<ReviewDb> schema;
 | 
			
		||||
  private final SitePaths site;
 | 
			
		||||
  private final ReviewDbSchemaCreator creator;
 | 
			
		||||
  private final Provider<ReviewDbSchemaVersion> updater;
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  ReviewDbSchemaUpdater(
 | 
			
		||||
      @ReviewDbFactory SchemaFactory<ReviewDb> schema,
 | 
			
		||||
      SitePaths site,
 | 
			
		||||
      ReviewDbSchemaCreator creator,
 | 
			
		||||
      Injector parent) {
 | 
			
		||||
    this.schema = schema;
 | 
			
		||||
    this.site = site;
 | 
			
		||||
    this.creator = creator;
 | 
			
		||||
    this.updater = buildInjector(parent).getProvider(ReviewDbSchemaVersion.class);
 | 
			
		||||
  }
 | 
			
		||||
@@ -119,8 +114,6 @@ public class ReviewDbSchemaUpdater {
 | 
			
		||||
        } catch (SQLException e) {
 | 
			
		||||
          throw new OrmException("Cannot upgrade schema", e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        updateSystemConfig(db);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -137,17 +130,4 @@ public class ReviewDbSchemaUpdater {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private void updateSystemConfig(ReviewDb db) throws OrmException {
 | 
			
		||||
    final SystemConfig sc = db.systemConfig().get(new SystemConfig.Key());
 | 
			
		||||
    if (sc == null) {
 | 
			
		||||
      throw new OrmException("No record in system_config table");
 | 
			
		||||
    }
 | 
			
		||||
    try {
 | 
			
		||||
      sc.sitePath = site.site_path.toRealPath().normalize().toString();
 | 
			
		||||
    } catch (IOException e) {
 | 
			
		||||
      sc.sitePath = site.site_path.toAbsolutePath().normalize().toString();
 | 
			
		||||
    }
 | 
			
		||||
    db.systemConfig().update(Collections.singleton(sc));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@ import java.util.concurrent.TimeUnit;
 | 
			
		||||
/** A version of the database schema. */
 | 
			
		||||
public abstract class ReviewDbSchemaVersion {
 | 
			
		||||
  /** The current schema version. */
 | 
			
		||||
  public static final Class<Schema_169> C = Schema_169.class;
 | 
			
		||||
  public static final Class<Schema_170> C = Schema_170.class;
 | 
			
		||||
 | 
			
		||||
  public static int getBinaryVersion() {
 | 
			
		||||
    return guessVersion(C);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								java/com/google/gerrit/server/schema/Schema_170.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								java/com/google/gerrit/server/schema/Schema_170.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
// Copyright (C) 2018 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.schema;
 | 
			
		||||
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
 | 
			
		||||
public class Schema_170 extends ReviewDbSchemaVersion {
 | 
			
		||||
  @Inject
 | 
			
		||||
  Schema_170(Provider<Schema_169> prior) {
 | 
			
		||||
    super(prior);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -29,6 +29,8 @@ import org.eclipse.jgit.lib.Repository;
 | 
			
		||||
import org.kohsuke.args4j.Argument;
 | 
			
		||||
 | 
			
		||||
public abstract class AbstractGitCommand extends BaseCommand {
 | 
			
		||||
  private static final String GIT_PROTOCOL = "GIT_PROTOCOL";
 | 
			
		||||
 | 
			
		||||
  @Argument(index = 0, metaVar = "PROJECT.git", required = true, usage = "project name")
 | 
			
		||||
  protected ProjectState projectState;
 | 
			
		||||
 | 
			
		||||
@@ -45,9 +47,15 @@ public abstract class AbstractGitCommand extends BaseCommand {
 | 
			
		||||
  protected Repository repo;
 | 
			
		||||
  protected Project.NameKey projectName;
 | 
			
		||||
  protected Project project;
 | 
			
		||||
  protected String[] extraParameters;
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void start(Environment env) {
 | 
			
		||||
    String gitProtocol = env.getEnv().get(GIT_PROTOCOL);
 | 
			
		||||
    if (gitProtocol != null) {
 | 
			
		||||
      extraParameters = gitProtocol.split(":");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Context ctx = context.subContext(newSession(), context.getCommandLine());
 | 
			
		||||
    final Context old = sshScope.set(ctx);
 | 
			
		||||
    try {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@
 | 
			
		||||
package com.google.gerrit.sshd;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ListMultimap;
 | 
			
		||||
import com.google.common.collect.Multimap;
 | 
			
		||||
import com.google.common.collect.MultimapBuilder;
 | 
			
		||||
import com.google.gerrit.extensions.events.LifecycleListener;
 | 
			
		||||
import com.google.gerrit.server.CurrentUser;
 | 
			
		||||
@@ -24,6 +25,8 @@ import com.google.gerrit.server.audit.AuditService;
 | 
			
		||||
import com.google.gerrit.server.audit.SshAuditEvent;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigKey;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
 | 
			
		||||
import com.google.gerrit.server.config.GerritConfigListener;
 | 
			
		||||
import com.google.gerrit.server.config.GerritServerConfig;
 | 
			
		||||
import com.google.gerrit.server.ioutil.HexFormat;
 | 
			
		||||
@@ -33,8 +36,6 @@ import com.google.gerrit.sshd.SshScope.Context;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
import com.google.inject.Singleton;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import org.apache.log4j.AsyncAppender;
 | 
			
		||||
import org.apache.log4j.Level;
 | 
			
		||||
import org.apache.log4j.Logger;
 | 
			
		||||
@@ -318,25 +319,22 @@ class SshLog implements LifecycleListener, GerritConfigListener {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public List<ConfigUpdatedEvent.Update> configUpdated(ConfigUpdatedEvent event) {
 | 
			
		||||
  public Multimap<UpdateResult, ConfigUpdateEntry> configUpdated(ConfigUpdatedEvent event) {
 | 
			
		||||
    ConfigKey sshdRequestLog = ConfigKey.create("sshd", "requestLog");
 | 
			
		||||
    if (!event.isValueUpdated(sshdRequestLog)) {
 | 
			
		||||
      return Collections.emptyList();
 | 
			
		||||
      return ConfigUpdatedEvent.NO_UPDATES;
 | 
			
		||||
    }
 | 
			
		||||
    boolean stateUpdated;
 | 
			
		||||
    try {
 | 
			
		||||
      boolean enabled = event.getNewConfig().getBoolean("sshd", "requestLog", true);
 | 
			
		||||
 | 
			
		||||
      if (enabled) {
 | 
			
		||||
        stateUpdated = enableLogging();
 | 
			
		||||
      } else {
 | 
			
		||||
        stateUpdated = disableLogging();
 | 
			
		||||
      }
 | 
			
		||||
      return stateUpdated
 | 
			
		||||
          ? Collections.singletonList(event.accept(sshdRequestLog))
 | 
			
		||||
          : Collections.emptyList();
 | 
			
		||||
      return stateUpdated ? event.accept(sshdRequestLog) : ConfigUpdatedEvent.NO_UPDATES;
 | 
			
		||||
    } catch (IllegalArgumentException iae) {
 | 
			
		||||
      return Collections.singletonList(event.reject(sshdRequestLog));
 | 
			
		||||
      return event.reject(sshdRequestLog);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,16 +16,15 @@ package com.google.gerrit.sshd.commands;
 | 
			
		||||
 | 
			
		||||
import static com.google.gerrit.sshd.CommandMetaData.Mode.MASTER_OR_SLAVE;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.Multimap;
 | 
			
		||||
import com.google.gerrit.common.data.GlobalCapability;
 | 
			
		||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
 | 
			
		||||
import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
 | 
			
		||||
import com.google.gerrit.server.config.GerritServerConfigReloader;
 | 
			
		||||
import com.google.gerrit.sshd.CommandMetaData;
 | 
			
		||||
import com.google.gerrit.sshd.SshCommand;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/** Issues a reload of gerrit.config. */
 | 
			
		||||
@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
 | 
			
		||||
@@ -39,31 +38,16 @@ public class ReloadConfig extends SshCommand {
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected void run() throws Failure {
 | 
			
		||||
    List<ConfigUpdatedEvent.Update> updates = gerritServerConfigReloader.reloadConfig();
 | 
			
		||||
    Multimap<UpdateResult, ConfigUpdateEntry> updates = gerritServerConfigReloader.reloadConfig();
 | 
			
		||||
    if (updates.isEmpty()) {
 | 
			
		||||
      stdout.println("No config entries updated!");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Print out UpdateResult.{ACCEPTED|REJECTED} entries grouped by their type
 | 
			
		||||
    for (UpdateResult updateResult : UpdateResult.values()) {
 | 
			
		||||
      List<ConfigUpdatedEvent.Update> filteredUpdates = filterUpdates(updates, updateResult);
 | 
			
		||||
      if (filteredUpdates.isEmpty()) {
 | 
			
		||||
        continue;
 | 
			
		||||
    for (UpdateResult result : updates.keySet()) {
 | 
			
		||||
      stdout.println(result.toString() + " configuration changes:");
 | 
			
		||||
      updates.get(result).forEach(cfgEntry -> stdout.println(cfgEntry.toString()));
 | 
			
		||||
    }
 | 
			
		||||
      stdout.println(updateResult.toString() + " configuration changes:");
 | 
			
		||||
      filteredUpdates
 | 
			
		||||
          .stream()
 | 
			
		||||
          .flatMap(update -> update.getConfigUpdates().stream())
 | 
			
		||||
          .forEach(cfgEntry -> stdout.println(cfgEntry.toString()));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public static List<ConfigUpdatedEvent.Update> filterUpdates(
 | 
			
		||||
      List<ConfigUpdatedEvent.Update> updates, UpdateResult result) {
 | 
			
		||||
    return updates
 | 
			
		||||
        .stream()
 | 
			
		||||
        .filter(update -> update.getResult() == result)
 | 
			
		||||
        .collect(Collectors.toList());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.sshd.commands;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ImmutableList;
 | 
			
		||||
import com.google.common.collect.Lists;
 | 
			
		||||
import com.google.gerrit.extensions.registration.DynamicSet;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.AuthException;
 | 
			
		||||
@@ -52,7 +53,6 @@ final class Upload extends AbstractGitCommand {
 | 
			
		||||
    PermissionBackend.ForProject perm =
 | 
			
		||||
        permissionBackend.user(user).project(projectState.getNameKey());
 | 
			
		||||
    try {
 | 
			
		||||
 | 
			
		||||
      perm.check(ProjectPermission.RUN_UPLOAD_PACK);
 | 
			
		||||
    } catch (AuthException e) {
 | 
			
		||||
      throw new Failure(1, "fatal: upload-pack not permitted on this server");
 | 
			
		||||
@@ -65,6 +65,9 @@ final class Upload extends AbstractGitCommand {
 | 
			
		||||
    up.setPackConfig(config.getPackConfig());
 | 
			
		||||
    up.setTimeout(config.getTimeout());
 | 
			
		||||
    up.setPostUploadHook(PostUploadHookChain.newChain(Lists.newArrayList(postUploadHooks)));
 | 
			
		||||
    if (config.enableProtocolV2() && extraParameters != null) {
 | 
			
		||||
      up.setExtraParameters(ImmutableList.copyOf(extraParameters));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    List<PreUploadHook> allPreUploadHooks = Lists.newArrayList(preUploadHooks);
 | 
			
		||||
    allPreUploadHooks.add(
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,6 @@ import com.google.gerrit.reviewdb.server.PatchSetAccess;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.PatchSetApprovalAccess;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.SchemaVersionAccess;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.SystemConfigAccess;
 | 
			
		||||
import com.google.gwtorm.server.Access;
 | 
			
		||||
import com.google.gwtorm.server.StatementExecutor;
 | 
			
		||||
 | 
			
		||||
@@ -70,11 +69,6 @@ public class DisabledReviewDb implements ReviewDb {
 | 
			
		||||
    throw new Disabled();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public SystemConfigAccess systemConfig() {
 | 
			
		||||
    throw new Disabled();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public ChangeAccess changes() {
 | 
			
		||||
    throw new Disabled();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										112
									
								
								java/com/google/gerrit/testing/FakeGroupAuditService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								java/com/google/gerrit/testing/FakeGroupAuditService.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
			
		||||
// Copyright (C) 2018 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.testing;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ImmutableSet;
 | 
			
		||||
import com.google.gerrit.extensions.registration.DynamicSet;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Account;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.AccountGroup;
 | 
			
		||||
import com.google.gerrit.server.AuditEvent;
 | 
			
		||||
import com.google.gerrit.server.audit.AuditListener;
 | 
			
		||||
import com.google.gerrit.server.audit.group.GroupAuditListener;
 | 
			
		||||
import com.google.gerrit.server.audit.group.GroupMemberAuditEvent;
 | 
			
		||||
import com.google.gerrit.server.audit.group.GroupSubgroupAuditEvent;
 | 
			
		||||
import com.google.gerrit.server.group.GroupAuditService;
 | 
			
		||||
import com.google.gerrit.server.plugincontext.PluginSetContext;
 | 
			
		||||
import com.google.inject.AbstractModule;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Singleton;
 | 
			
		||||
import java.sql.Timestamp;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@Singleton
 | 
			
		||||
public class FakeGroupAuditService implements GroupAuditService {
 | 
			
		||||
 | 
			
		||||
  private final PluginSetContext<GroupAuditListener> groupAuditListeners;
 | 
			
		||||
  private final PluginSetContext<AuditListener> auditListeners;
 | 
			
		||||
 | 
			
		||||
  public static class Module extends AbstractModule {
 | 
			
		||||
    @Override
 | 
			
		||||
    public void configure() {
 | 
			
		||||
      DynamicSet.setOf(binder(), GroupAuditListener.class);
 | 
			
		||||
      DynamicSet.setOf(binder(), AuditListener.class);
 | 
			
		||||
      bind(GroupAuditService.class).to(FakeGroupAuditService.class);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  public FakeGroupAuditService(
 | 
			
		||||
      PluginSetContext<GroupAuditListener> groupAuditListeners,
 | 
			
		||||
      PluginSetContext<AuditListener> auditListeners) {
 | 
			
		||||
    this.groupAuditListeners = groupAuditListeners;
 | 
			
		||||
    this.auditListeners = auditListeners;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public List<AuditEvent> auditEvents = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
  public void clearEvents() {
 | 
			
		||||
    auditEvents.clear();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void dispatch(AuditEvent action) {
 | 
			
		||||
    auditEvents.add(action);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void dispatchAddMembers(
 | 
			
		||||
      Account.Id actor,
 | 
			
		||||
      AccountGroup.UUID updatedGroup,
 | 
			
		||||
      ImmutableSet<Account.Id> addedMembers,
 | 
			
		||||
      Timestamp addedOn) {
 | 
			
		||||
    GroupMemberAuditEvent event =
 | 
			
		||||
        GroupMemberAuditEvent.create(actor, updatedGroup, addedMembers, addedOn);
 | 
			
		||||
    groupAuditListeners.runEach(l -> l.onAddMembers(event));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void dispatchDeleteMembers(
 | 
			
		||||
      Account.Id actor,
 | 
			
		||||
      AccountGroup.UUID updatedGroup,
 | 
			
		||||
      ImmutableSet<Account.Id> deletedMembers,
 | 
			
		||||
      Timestamp deletedOn) {
 | 
			
		||||
    GroupMemberAuditEvent event =
 | 
			
		||||
        GroupMemberAuditEvent.create(actor, updatedGroup, deletedMembers, deletedOn);
 | 
			
		||||
    groupAuditListeners.runEach(l -> l.onDeleteMembers(event));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void dispatchAddSubgroups(
 | 
			
		||||
      Account.Id actor,
 | 
			
		||||
      AccountGroup.UUID updatedGroup,
 | 
			
		||||
      ImmutableSet<AccountGroup.UUID> addedSubgroups,
 | 
			
		||||
      Timestamp addedOn) {
 | 
			
		||||
    GroupSubgroupAuditEvent event =
 | 
			
		||||
        GroupSubgroupAuditEvent.create(actor, updatedGroup, addedSubgroups, addedOn);
 | 
			
		||||
    groupAuditListeners.runEach(l -> l.onAddSubgroups(event));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void dispatchDeleteSubgroups(
 | 
			
		||||
      Account.Id actor,
 | 
			
		||||
      AccountGroup.UUID updatedGroup,
 | 
			
		||||
      ImmutableSet<AccountGroup.UUID> deletedSubgroups,
 | 
			
		||||
      Timestamp deletedOn) {
 | 
			
		||||
    GroupSubgroupAuditEvent event =
 | 
			
		||||
        GroupSubgroupAuditEvent.create(actor, updatedGroup, deletedSubgroups, deletedOn);
 | 
			
		||||
    groupAuditListeners.runEach(l -> l.onDeleteSubgroups(event));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -20,7 +20,6 @@ import com.google.gerrit.lifecycle.LifecycleManager;
 | 
			
		||||
import com.google.gerrit.pgm.init.index.elasticsearch.ElasticIndexModuleOnInit;
 | 
			
		||||
import com.google.gerrit.pgm.init.index.lucene.LuceneIndexModuleOnInit;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.SystemConfig;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.server.index.IndexModule;
 | 
			
		||||
import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
 | 
			
		||||
@@ -127,12 +126,6 @@ public class InMemoryDatabase implements SchemaFactory<ReviewDb> {
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public SystemConfig getSystemConfig() throws OrmException {
 | 
			
		||||
    try (ReviewDb c = open()) {
 | 
			
		||||
      return c.systemConfig().get(new SystemConfig.Key());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public CurrentSchemaVersion getSchemaVersion() throws OrmException {
 | 
			
		||||
    try (ReviewDb c = open()) {
 | 
			
		||||
      return c.schemaVersion().get(new CurrentSchemaVersion.Key());
 | 
			
		||||
 
 | 
			
		||||
@@ -102,7 +102,7 @@ public class PRED_commit_delta_4 extends Predicate.P4 {
 | 
			
		||||
        String oldName = patch.getOldName();
 | 
			
		||||
        Patch.ChangeType changeType = patch.getChangeType();
 | 
			
		||||
 | 
			
		||||
        if (newName.equals("/COMMIT_MSG")) {
 | 
			
		||||
        if (Patch.isMagic(newName)) {
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
 | 
			
		||||
package gerrit;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Patch;
 | 
			
		||||
import com.google.gerrit.server.patch.PatchList;
 | 
			
		||||
import com.google.gerrit.server.patch.PatchListEntry;
 | 
			
		||||
import com.google.gerrit.server.patch.Text;
 | 
			
		||||
@@ -90,7 +91,7 @@ public class PRED_commit_edits_2 extends Predicate.P2 {
 | 
			
		||||
        String newName = entry.getNewName();
 | 
			
		||||
        String oldName = entry.getOldName();
 | 
			
		||||
 | 
			
		||||
        if (newName.equals("/COMMIT_MSG")) {
 | 
			
		||||
        if (Patch.isMagic(newName)) {
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,68 @@
 | 
			
		||||
// Copyright (C) 2018 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.acceptance.git;
 | 
			
		||||
 | 
			
		||||
import static com.google.common.truth.Truth.assertThat;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.server.AuditEvent;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import org.eclipse.jgit.transport.CredentialsProvider;
 | 
			
		||||
import org.eclipse.jgit.transport.RefSpec;
 | 
			
		||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
public class GitOverHttpServletIT extends AbstractPushForReview {
 | 
			
		||||
 | 
			
		||||
  @Before
 | 
			
		||||
  public void beforeEach() throws Exception {
 | 
			
		||||
    CredentialsProvider.setDefault(
 | 
			
		||||
        new UsernamePasswordCredentialsProvider(admin.username, admin.httpPassword));
 | 
			
		||||
    selectProtocol(AbstractPushForReview.Protocol.HTTP);
 | 
			
		||||
    auditService.clearEvents();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void receivePackAuditEventLog() throws Exception {
 | 
			
		||||
    testRepo
 | 
			
		||||
        .git()
 | 
			
		||||
        .push()
 | 
			
		||||
        .setRemote("origin")
 | 
			
		||||
        .setRefSpecs(new RefSpec("HEAD:refs/for/master"))
 | 
			
		||||
        .call();
 | 
			
		||||
 | 
			
		||||
    // Git smart protocol makes two requests:
 | 
			
		||||
    // https://github.com/git/git/blob/master/Documentation/technical/http-protocol.txt
 | 
			
		||||
    assertThat(auditService.auditEvents.size()).isEqualTo(2);
 | 
			
		||||
 | 
			
		||||
    AuditEvent e = auditService.auditEvents.get(1);
 | 
			
		||||
    assertThat(e.who.getAccountId()).isEqualTo(admin.id);
 | 
			
		||||
    assertThat(e.what).endsWith("/git-receive-pack");
 | 
			
		||||
    assertThat(e.params).isEmpty();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void uploadPackAuditEventLog() throws Exception {
 | 
			
		||||
    testRepo.git().fetch().call();
 | 
			
		||||
 | 
			
		||||
    assertThat(auditService.auditEvents.size()).isEqualTo(1);
 | 
			
		||||
 | 
			
		||||
    AuditEvent e = auditService.auditEvents.get(0);
 | 
			
		||||
    assertThat(e.who.toString()).isEqualTo("ANONYMOUS");
 | 
			
		||||
    assertThat(e.params.get("service"))
 | 
			
		||||
        .containsExactlyElementsIn(Collections.singletonList("git-upload-pack"));
 | 
			
		||||
    assertThat(e.what).endsWith("service=git-upload-pack");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -31,7 +31,6 @@ import com.google.gwtorm.jdbc.JdbcSchema;
 | 
			
		||||
import com.google.gwtorm.server.OrmException;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.sql.ResultSet;
 | 
			
		||||
import java.sql.SQLException;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
@@ -63,7 +62,7 @@ public class ReviewDbSchemaCreatorTest {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void getCauses_CreateSchema() throws OrmException, SQLException, IOException {
 | 
			
		||||
  public void getCauses_CreateSchema() throws OrmException, SQLException {
 | 
			
		||||
    // Initially the schema should be empty.
 | 
			
		||||
    String[] types = {"TABLE", "VIEW"};
 | 
			
		||||
    try (JdbcSchema d = (JdbcSchema) db.open();
 | 
			
		||||
@@ -82,7 +81,6 @@ public class ReviewDbSchemaCreatorTest {
 | 
			
		||||
    if (sitePath.getName().equals(".")) {
 | 
			
		||||
      sitePath = sitePath.getParentFile();
 | 
			
		||||
    }
 | 
			
		||||
    assertThat(db.getSystemConfig().sitePath).isEqualTo(sitePath.getCanonicalPath());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private LabelTypes getLabelTypes() throws Exception {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@ import com.google.gerrit.extensions.config.FactoryModule;
 | 
			
		||||
import com.google.gerrit.lifecycle.LifecycleManager;
 | 
			
		||||
import com.google.gerrit.metrics.DisabledMetricMaker;
 | 
			
		||||
import com.google.gerrit.metrics.MetricMaker;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.SystemConfig;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.server.GerritPersonIdent;
 | 
			
		||||
import com.google.gerrit.server.GerritPersonIdentProvider;
 | 
			
		||||
@@ -148,7 +147,5 @@ public class ReviewDbSchemaUpdaterTest {
 | 
			
		||||
    u.update(new TestUpdateUI());
 | 
			
		||||
 | 
			
		||||
    db.assertSchemaVersion();
 | 
			
		||||
    final SystemConfig sc = db.getSystemConfig();
 | 
			
		||||
    assertThat(sc.sitePath).isEqualTo(paths.site_path.toAbsolutePath().toString());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
 | 
			
		||||
  <filter>
 | 
			
		||||
    <filter-name>guiceFilter</filter-name>
 | 
			
		||||
    <filter-class>com.google.gerrit.httpd.WebAppInitializer</filter-class>
 | 
			
		||||
    <filter-class>com.google.gerrit.httpd.init.WebAppInitializer</filter-class>
 | 
			
		||||
  </filter>
 | 
			
		||||
  <filter-mapping>
 | 
			
		||||
    <filter-name>guiceFilter</filter-name>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user