Merge "Add a shared pre-commit to run eslintfix for frontend code changes"
diff --git a/java/com/google/gerrit/pgm/init/InitSshd.java b/java/com/google/gerrit/pgm/init/InitSshd.java
index 68bdefc..c0adbe7 100644
--- a/java/com/google/gerrit/pgm/init/InitSshd.java
+++ b/java/com/google/gerrit/pgm/init/InitSshd.java
@@ -124,7 +124,7 @@
"-q" /* quiet */,
"-t",
"ed25519",
- "-P",
+ "-N",
emptyPassphraseArg,
"-C",
comment,
@@ -152,7 +152,7 @@
"ecdsa",
"-b",
"256",
- "-P",
+ "-N",
emptyPassphraseArg,
"-C",
comment,
@@ -180,7 +180,7 @@
"ecdsa",
"-b",
"384",
- "-P",
+ "-N",
emptyPassphraseArg,
"-C",
comment,
@@ -208,7 +208,7 @@
"ecdsa",
"-b",
"521",
- "-P",
+ "-N",
emptyPassphraseArg,
"-C",
comment,
diff --git a/java/com/google/gerrit/server/restapi/account/GetAgreements.java b/java/com/google/gerrit/server/restapi/account/GetAgreements.java
index 5feca66..572b489 100644
--- a/java/com/google/gerrit/server/restapi/account/GetAgreements.java
+++ b/java/com/google/gerrit/server/restapi/account/GetAgreements.java
@@ -29,6 +29,8 @@
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResource;
import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.permissions.GlobalPermission;
+import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.restapi.config.AgreementJson;
@@ -48,17 +50,20 @@
private final ProjectCache projectCache;
private final AgreementJson agreementJson;
private final boolean agreementsEnabled;
+ private final PermissionBackend permissionBackend;
@Inject
GetAgreements(
Provider<CurrentUser> self,
ProjectCache projectCache,
AgreementJson agreementJson,
+ PermissionBackend permissionBackend,
@GerritServerConfig Config config) {
this.self = self;
this.projectCache = projectCache;
this.agreementJson = agreementJson;
this.agreementsEnabled = config.getBoolean("auth", "contributorAgreements", false);
+ this.permissionBackend = permissionBackend;
}
@Override
@@ -74,7 +79,11 @@
IdentifiedUser user = self.get().asIdentifiedUser();
if (user != resource.getUser()) {
- throw new AuthException("not allowed to get contributor agreements");
+ try {
+ permissionBackend.user(user).check(GlobalPermission.ADMINISTRATE_SERVER);
+ } catch (AuthException e) {
+ throw new AuthException("not allowed to get contributor agreements", e);
+ }
}
List<AgreementInfo> results = new ArrayList<>();
diff --git a/java/com/google/gerrit/server/update/RetryHelper.java b/java/com/google/gerrit/server/update/RetryHelper.java
index c3a88f2..9f38156 100644
--- a/java/com/google/gerrit/server/update/RetryHelper.java
+++ b/java/com/google/gerrit/server/update/RetryHelper.java
@@ -87,7 +87,7 @@
@Nullable
abstract Duration timeout();
- abstract Optional<String> caller();
+ abstract Optional<String> actionName();
abstract Optional<Predicate<Throwable>> retryWithTrace();
@@ -99,7 +99,7 @@
public abstract Builder timeout(Duration timeout);
- public abstract Builder caller(String caller);
+ public abstract Builder actionName(String caller);
public abstract Builder retryWithTrace(Predicate<Throwable> exceptionPredicate);
@@ -458,7 +458,7 @@
return true;
}
- String actionName = opts.caller().orElse("N/A");
+ String actionName = opts.actionName().orElse("N/A");
// Exception hooks may identify additional exceptions for retry.
if (exceptionHooks.stream()
@@ -507,7 +507,7 @@
logger.atFine().log("%s was attempted %d times", actionType, listener.getAttemptCount());
metrics.attemptCounts.incrementBy(
actionType,
- opts.caller().orElse("N/A"),
+ opts.actionName().orElse("N/A"),
listener.getCause().map(this::formatCause).orElse("_unknown"),
listener.getAttemptCount() - 1);
}
@@ -557,7 +557,7 @@
if (e instanceof RetryException) {
metrics.timeoutCount.increment(
actionType,
- opts.caller().orElse("N/A"),
+ opts.actionName().orElse("N/A"),
e.getCause() != null ? formatCause(e.getCause()) : "_unknown");
}
if (e.getCause() != null) {
diff --git a/java/com/google/gerrit/server/update/RetryableAction.java b/java/com/google/gerrit/server/update/RetryableAction.java
index 336a238..9a2807a 100644
--- a/java/com/google/gerrit/server/update/RetryableAction.java
+++ b/java/com/google/gerrit/server/update/RetryableAction.java
@@ -67,7 +67,7 @@
this.retryHelper = requireNonNull(retryHelper, "retryHelper");
this.actionType = requireNonNull(actionType, "actionType");
this.action = requireNonNull(action, "action");
- options.caller(requireNonNull(actionName, "actionName"));
+ options.actionName(requireNonNull(actionName, "actionName"));
}
/**
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
index 3bb0338..11ca391 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
@@ -178,6 +178,18 @@
}
@Test
+ public void listAgreementPermission() throws Exception {
+ assume().that(isContributorAgreementsEnabled()).isTrue();
+ requestScopeOperations.setApiUser(admin.id());
+ // Allowed.
+ gApi.accounts().id(user.id().get()).listAgreements();
+ requestScopeOperations.setApiUser(user.id());
+
+ // Not allowed.
+ assertThrows(AuthException.class, () -> gApi.accounts().id(admin.id().get()).listAgreements());
+ }
+
+ @Test
public void signAgreementAsOtherUser() throws Exception {
assume().that(isContributorAgreementsEnabled()).isTrue();
assertThat(gApi.accounts().self().get().name).isNotEqualTo("admin");
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
index 5eb8b09..c6743e8 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
@@ -560,6 +560,10 @@
isStartOfRange ? 'startOfRange' : '');
const shaNode = this._createElement('span', 'sha');
shaNode.innerText = commit.id.substr(0, 7);
+ shaNode.onclick = function() {
+ location.href = '/q/' + shaNode.innerText;
+ };
+
blameNode.appendChild(shaNode);
blameNode.append(` on ${date} by ${commit.author}`);
return blameNode;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
index 3b64f55..92c2c37 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -273,6 +273,8 @@
}
td.blame .sha {
font-family: var(--monospace-font-family);
+ color: var(--link-color);
+ cursor: pointer;
}
.full-width td.blame {
overflow: hidden;
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit.js
index 546b9f3..e48ef91 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit.js
@@ -156,4 +156,41 @@
// Preloaded plugins should be installed after Gerrit.install() is set,
// since plugin preloader substitutes Gerrit.install() temporarily.
Gerrit._pluginLoader.installPreloadedPlugins();
+
+ // TODO(taoalpha): List all internal supported event names.
+ // Also convert this to inherited class once we move Gerrit to class.
+ Gerrit._eventEmitter = new EventEmitter();
+ ['addListener',
+ 'dispatch',
+ 'emit',
+ 'off',
+ 'on',
+ 'once',
+ 'removeAllListeners',
+ 'removeListener',
+ ].forEach(method => {
+ /**
+ * Enabling EventEmitter interface on Gerrit.
+ *
+ * This will enable to signal across different parts of js code without relying on DOM,
+ * including core to core, plugin to plugin and also core to plugin.
+ *
+ * @example
+ *
+ * // Emit this event from pluginA
+ * Gerrit.install(pluginA => {
+ * fetch("some-api").then(() => {
+ * Gerrit.on("your-special-event", {plugin: pluginA});
+ * });
+ * });
+ *
+ * // Listen on your-special-event from pluignB
+ * Gerrit.install(pluginB => {
+ * Gerrit.on("your-special-event", ({plugin}) => {
+ * // do something, plugin is pluginA
+ * });
+ * });
+ */
+ Gerrit[method] = Gerrit._eventEmitter[method].bind(Gerrit._eventEmitter);
+ });
})(window);
\ No newline at end of file
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
index 9ff1297..6dc0309 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
@@ -381,40 +381,4 @@
};
window.Plugin = Plugin;
- // TODO(taoalpha): List all internal supported event names.
- // Also convert this to inherited class once we move Gerrit to class.
- Gerrit._eventEmitter = new EventEmitter();
- ['addListener',
- 'dispatch',
- 'emit',
- 'off',
- 'on',
- 'once',
- 'removeAllListeners',
- 'removeListener',
- ].forEach(method => {
- /**
- * Enabling EventEmitter interface on Gerrit.
- *
- * This will enable to signal across different parts of js code without relying on DOM,
- * including core to core, plugin to plugin and also core to plugin.
- *
- * @example
- *
- * // Emit this event from pluginA
- * Gerrit.install(pluginA => {
- * fetch("some-api").then(() => {
- * Gerrit.on("your-special-event", {plugin: pluginA});
- * });
- * });
- *
- * // Listen on your-special-event from pluignB
- * Gerrit.install(pluginB => {
- * Gerrit.on("your-special-event", ({plugin}) => {
- * // do something, plugin is pluginA
- * });
- * });
- */
- Gerrit[method] = Gerrit._eventEmitter[method].bind(Gerrit._eventEmitter);
- });
})(window);