Merge branch 'stable-3.0'

* stable-3.0:
  Update NoteDb documentation for 3.0
  NotificationEmail: Fix eliding project name without slash
  Clean up NotificationEmailTest
  Update links to Google individual and corporate CLA pages
  Bazel: Remove iteration over depset
  dev-bazel: Fix section title sequence
  Elasticsearch: Exclude types from V7 which deprecates them
  Print test errors by default
  Send an email notification when the HTTP password is deleted or changed
  Send email notification when SSH key or GPG key is removed
  StaticModule: Remove unused GERRIT_UI_COOKIE
  Show progress on number of users migrated during schema migration 146

Additional changes in this merge to adapt to master:

- Move changes in dev-contributing.txt to dev-cla.txt

Change-Id: I5b9c2e454c551ccfcbd2ecaa1653044cc9597382
This commit is contained in:
David Pursehouse
2019-05-22 13:29:46 +09:00
27 changed files with 692 additions and 72 deletions

View File

@@ -20,8 +20,10 @@ import com.google.gerrit.server.mail.send.AddKeySender;
import com.google.gerrit.server.mail.send.AddReviewerSender;
import com.google.gerrit.server.mail.send.CommentSender;
import com.google.gerrit.server.mail.send.CreateChangeSender;
import com.google.gerrit.server.mail.send.DeleteKeySender;
import com.google.gerrit.server.mail.send.DeleteReviewerSender;
import com.google.gerrit.server.mail.send.DeleteVoteSender;
import com.google.gerrit.server.mail.send.HttpPasswordUpdateSender;
import com.google.gerrit.server.mail.send.MergedSender;
import com.google.gerrit.server.mail.send.RegisterNewEmailSender;
import com.google.gerrit.server.mail.send.ReplacePatchSetSender;
@@ -37,8 +39,10 @@ public class EmailModule extends FactoryModule {
factory(AddReviewerSender.Factory.class);
factory(CommentSender.Factory.class);
factory(CreateChangeSender.Factory.class);
factory(DeleteKeySender.Factory.class);
factory(DeleteReviewerSender.Factory.class);
factory(DeleteVoteSender.Factory.class);
factory(HttpPasswordUpdateSender.Factory.class);
factory(MergedSender.Factory.class);
factory(RegisterNewEmailSender.Factory.class);
factory(ReplacePatchSetSender.Factory.class);

View File

@@ -0,0 +1,150 @@
// Copyright (C) 2019 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.mail.send;
import com.google.common.base.Joiner;
import com.google.gerrit.exceptions.EmailException;
import com.google.gerrit.extensions.api.changes.RecipientType;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.mail.Address;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountSshKey;
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.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.util.Collections;
import java.util.List;
public class DeleteKeySender extends OutgoingEmail {
public interface Factory {
DeleteKeySender create(IdentifiedUser user, AccountSshKey sshKey);
DeleteKeySender create(IdentifiedUser user, List<String> gpgKeyFingerprints);
}
private final PermissionBackend permissionBackend;
private final IdentifiedUser callingUser;
private final IdentifiedUser user;
private final AccountSshKey sshKey;
private final List<String> gpgKeyFingerprints;
@AssistedInject
public DeleteKeySender(
EmailArguments ea,
PermissionBackend permissionBackend,
IdentifiedUser callingUser,
@Assisted IdentifiedUser user,
@Assisted AccountSshKey sshKey) {
super(ea, "deletekey");
this.permissionBackend = permissionBackend;
this.callingUser = callingUser;
this.user = user;
this.gpgKeyFingerprints = Collections.emptyList();
this.sshKey = sshKey;
}
@AssistedInject
public DeleteKeySender(
EmailArguments ea,
PermissionBackend permissionBackend,
IdentifiedUser callingUser,
@Assisted IdentifiedUser user,
@Assisted List<String> gpgKeyFingerprints) {
super(ea, "deletekey");
this.permissionBackend = permissionBackend;
this.callingUser = callingUser;
this.user = user;
this.gpgKeyFingerprints = gpgKeyFingerprints;
this.sshKey = null;
}
@Override
protected void init() throws EmailException {
super.init();
setHeader("Subject", String.format("[Gerrit Code Review] %s Keys Deleted", getKeyType()));
add(RecipientType.TO, new Address(getEmail()));
}
@Override
protected boolean shouldSendMessage() {
if (user.equals(callingUser)) {
// Send email if the user self-removed a key; this notification is necessary to alert
// the user if their account was compromised and a key was unexpectedly deleted.
return true;
}
try {
// Don't email if an administrator removed a key on behalf of the user.
permissionBackend.user(callingUser).check(GlobalPermission.ADMINISTRATE_SERVER);
return false;
} catch (AuthException | PermissionBackendException e) {
// Send email if a non-administrator modified the keys, e.g. by MODIFY_ACCOUNT.
return true;
}
}
@Override
protected void format() throws EmailException {
appendText(textTemplate("DeleteKey"));
if (useHtml()) {
appendHtml(soyHtmlTemplate("DeleteKeyHtml"));
}
}
public String getEmail() {
return user.getAccount().getPreferredEmail();
}
public String getUserNameEmail() {
return getUserNameEmailFor(user.getAccountId());
}
public String getKeyType() {
if (sshKey != null) {
return "SSH";
} else if (gpgKeyFingerprints != null) {
return "GPG";
}
throw new IllegalStateException("key type is not SSH or GPG");
}
public String getSshKey() {
return (sshKey != null) ? sshKey.sshPublicKey() + "\n" : null;
}
public String getGpgKeyFingerprints() {
if (!gpgKeyFingerprints.isEmpty()) {
return Joiner.on("\n").join(gpgKeyFingerprints);
}
return null;
}
@Override
protected void setupSoyContext() {
super.setupSoyContext();
soyContextEmailData.put("email", getEmail());
soyContextEmailData.put("gpgKeyFingerprints", getGpgKeyFingerprints());
soyContextEmailData.put("keyType", getKeyType());
soyContextEmailData.put("sshKey", getSshKey());
soyContextEmailData.put("userNameEmail", getUserNameEmail());
}
@Override
protected boolean supportsHtml() {
return true;
}
}

View File

@@ -0,0 +1,81 @@
// Copyright (C) 2019 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.mail.send;
import com.google.gerrit.exceptions.EmailException;
import com.google.gerrit.extensions.api.changes.RecipientType;
import com.google.gerrit.mail.Address;
import com.google.gerrit.server.IdentifiedUser;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
public class HttpPasswordUpdateSender extends OutgoingEmail {
public interface Factory {
HttpPasswordUpdateSender create(IdentifiedUser user, String operation);
}
private final IdentifiedUser user;
private final String operation;
@AssistedInject
public HttpPasswordUpdateSender(
EmailArguments ea, @Assisted IdentifiedUser user, @Assisted String operation) {
super(ea, "HttpPasswordUpdate");
this.user = user;
this.operation = operation;
}
@Override
protected void init() throws EmailException {
super.init();
setHeader("Subject", "[Gerrit Code Review] HTTP password was " + operation);
add(RecipientType.TO, new Address(getEmail()));
}
@Override
protected boolean shouldSendMessage() {
// Always send an email if the HTTP password is updated.
return true;
}
@Override
protected void format() throws EmailException {
appendText(textTemplate("HttpPasswordUpdate"));
if (useHtml()) {
appendHtml(soyHtmlTemplate("HttpPasswordUpdateHtml"));
}
}
public String getEmail() {
return user.getAccount().getPreferredEmail();
}
public String getUserNameEmail() {
return getUserNameEmailFor(user.getAccountId());
}
@Override
protected void setupSoyContext() {
super.setupSoyContext();
soyContextEmailData.put("email", getEmail());
soyContextEmailData.put("userNameEmail", getUserNameEmail());
soyContextEmailData.put("operation", operation);
}
@Override
protected boolean supportsHtml() {
return true;
}
}

View File

@@ -47,6 +47,8 @@ public class MailSoyTofuProvider implements Provider<SoyTofu> {
"CommentHtml.soy",
"CommentFooter.soy",
"CommentFooterHtml.soy",
"DeleteKey.soy",
"DeleteKeyHtml.soy",
"DeleteReviewer.soy",
"DeleteReviewerHtml.soy",
"DeleteVote.soy",
@@ -56,6 +58,8 @@ public class MailSoyTofuProvider implements Provider<SoyTofu> {
"Footer.soy",
"FooterHtml.soy",
"HeaderHtml.soy",
"HttpPasswordUpdate.soy",
"HttpPasswordUpdateHtml.soy",
"Merged.soy",
"MergedHtml.soy",
"NewChange.soy",

View File

@@ -131,6 +131,9 @@ public abstract class NotificationEmail extends OutgoingEmail {
if (lastIndexSlash == 0) {
return projectName.substring(1); // Remove the first slash
}
if (lastIndexSlash == -1) { // No slash in the project name
return projectName;
}
return "..." + projectName.substring(lastIndexSlash + 1);
}