mirror of
https://github.com/google/nomulus
synced 2026-06-09 00:13:02 +00:00
Send email for packages over create limit (#1835)
* Send email for packages over create limit * Small change to query * Fix small nits
This commit is contained in:
@@ -13,17 +13,24 @@
|
||||
// limitations under the License.
|
||||
package google.registry.batch;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import com.google.common.primitives.Ints;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.domain.token.PackagePromotion;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.request.auth.Auth;
|
||||
import java.util.List;
|
||||
import google.registry.ui.server.SendEmailUtils;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* An action that checks all {@link PackagePromotion} objects for compliance with their max create
|
||||
@@ -37,6 +44,22 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/checkPackagesCompliance";
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private final SendEmailUtils sendEmailUtils;
|
||||
private final String packageCreateLimitEmailSubjectText;
|
||||
private final String packageCreateLimitEmailBodyText;
|
||||
private final String registrySupportEmail;
|
||||
|
||||
@Inject
|
||||
public CheckPackagesComplianceAction(
|
||||
SendEmailUtils sendEmailUtils,
|
||||
@Config("packageCreateLimitEmailSubjectText") String packageCreateLimitEmailSubjectText,
|
||||
@Config("packageCreateLimitEmailBodyText") String packageCreateLimitEmailBodyText,
|
||||
@Config("registrySupportEmail") String registrySupportEmail) {
|
||||
this.sendEmailUtils = sendEmailUtils;
|
||||
this.packageCreateLimitEmailSubjectText = packageCreateLimitEmailSubjectText;
|
||||
this.packageCreateLimitEmailBodyText = packageCreateLimitEmailBodyText;
|
||||
this.registrySupportEmail = registrySupportEmail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -46,19 +69,19 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
ImmutableList.Builder<PackagePromotion> packagesOverCreateLimit =
|
||||
new ImmutableList.Builder<>();
|
||||
for (PackagePromotion packagePromo : packages) {
|
||||
List<DomainHistory> creates =
|
||||
jpaTm()
|
||||
.query(
|
||||
"FROM DomainHistory WHERE current_package_token = :token AND"
|
||||
+ " modificationTime >= :lastBilling AND type = 'DOMAIN_CREATE'",
|
||||
DomainHistory.class)
|
||||
.setParameter("token", packagePromo.getToken().getKey().toString())
|
||||
.setParameter(
|
||||
"lastBilling", packagePromo.getNextBillingDate().minusYears(1))
|
||||
.getResultList();
|
||||
|
||||
if (creates.size() > packagePromo.getMaxCreates()) {
|
||||
int overage = creates.size() - packagePromo.getMaxCreates();
|
||||
Long creates =
|
||||
(Long)
|
||||
jpaTm()
|
||||
.query(
|
||||
"SELECT COUNT(*) FROM DomainHistory WHERE current_package_token ="
|
||||
+ " :token AND modificationTime >= :lastBilling AND type ="
|
||||
+ " 'DOMAIN_CREATE'")
|
||||
.setParameter("token", packagePromo.getToken().getKey().toString())
|
||||
.setParameter(
|
||||
"lastBilling", packagePromo.getNextBillingDate().minusYears(1))
|
||||
.getSingleResult();
|
||||
if (creates > packagePromo.getMaxCreates()) {
|
||||
int overage = Ints.saturatedCast(creates) - packagePromo.getMaxCreates();
|
||||
logger.atInfo().log(
|
||||
"Package with package token %s has exceeded their max domain creation limit"
|
||||
+ " by %d name(s).",
|
||||
@@ -72,9 +95,43 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
logger.atInfo().log(
|
||||
"Found %d packages over their create limit.",
|
||||
packagesOverCreateLimit.build().size());
|
||||
// TODO(sarahbot@) Send email to registrar and registry informing of creation
|
||||
// overage once email template is finalized.
|
||||
for (PackagePromotion packagePromotion : packagesOverCreateLimit.build()) {
|
||||
AllocationToken packageToken = tm().loadByKey(packagePromotion.getToken());
|
||||
Optional<Registrar> registrar =
|
||||
Registrar.loadByRegistrarIdCached(
|
||||
packageToken.getAllowedRegistrarIds().iterator().next());
|
||||
if (registrar.isPresent()) {
|
||||
String body =
|
||||
String.format(
|
||||
packageCreateLimitEmailBodyText,
|
||||
registrar.get().getRegistrarName(),
|
||||
packageToken.getToken(),
|
||||
registrySupportEmail);
|
||||
sendNotification(
|
||||
packageToken, packageCreateLimitEmailSubjectText, body, registrar.get());
|
||||
} else {
|
||||
logger.atSevere().log(
|
||||
String.format(
|
||||
"Could not find registrar for package token %s", packageToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendNotification(
|
||||
AllocationToken packageToken, String subject, String body, Registrar registrar) {
|
||||
logger.atInfo().log(
|
||||
String.format(
|
||||
"Compliance email sent to the %s registrar regarding the package with token" + " %s.",
|
||||
registrar.getRegistrarName(), packageToken.getToken()));
|
||||
sendEmailUtils.sendEmail(
|
||||
subject,
|
||||
body,
|
||||
Optional.of(registrySupportEmail),
|
||||
registrar.getContacts().stream()
|
||||
.filter(c -> c.getTypes().contains(RegistrarPoc.Type.ADMIN))
|
||||
.map(RegistrarPoc::getEmailAddress)
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1309,6 +1309,18 @@ public final class RegistryConfig {
|
||||
public static int provideHibernateJdbcBatchSize(RegistryConfigSettings config) {
|
||||
return config.hibernate.jdbcBatchSize;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("packageCreateLimitEmailSubjectText")
|
||||
public static String providePackageCreateLimitEmailSubjectText(RegistryConfigSettings config) {
|
||||
return config.packageMonitoring.packageCreateLimitEmailSubjectText;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("packageCreateLimitEmailBodyText")
|
||||
public static String providePackageCreateLimitEmailBodyText(RegistryConfigSettings config) {
|
||||
return config.packageMonitoring.packageCreateLimitEmailBodyText;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the App Engine project ID, which is based off the environment name. */
|
||||
|
||||
@@ -43,6 +43,7 @@ public class RegistryConfigSettings {
|
||||
public SslCertificateValidation sslCertificateValidation;
|
||||
public ContactHistory contactHistory;
|
||||
public DnsUpdate dnsUpdate;
|
||||
public PackageMonitoring packageMonitoring;
|
||||
|
||||
/** Configuration options that apply to the entire App Engine project. */
|
||||
public static class AppEngine {
|
||||
@@ -256,4 +257,10 @@ public class RegistryConfigSettings {
|
||||
public String registrySupportEmail;
|
||||
public String registryCcEmail;
|
||||
}
|
||||
|
||||
/** Configuration for package compliance monitoring. */
|
||||
public static class PackageMonitoring {
|
||||
public String packageCreateLimitEmailSubjectText;
|
||||
public String packageCreateLimitEmailBodyText;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,3 +535,21 @@ sslCertificateValidation:
|
||||
allowedEcdsaCurves:
|
||||
- secp256r1
|
||||
- secp384r1
|
||||
|
||||
# Configuration options for the package compliance monitoring
|
||||
packageMonitoring:
|
||||
# Email subject text to notify partners their package has exceeded the limit for domain creates
|
||||
packageCreateLimitEmailSubjectText: "NOTICE: Your Package Is Being Upgraded"
|
||||
# Email body text template notify partners their package has exceeded the limit for domain creates
|
||||
packageCreateLimitEmailBodyText: >
|
||||
Dear %1$s,
|
||||
|
||||
We are contacting you to inform you that your package with the package token
|
||||
%2$s has exceeded its limit for annual domain creations.
|
||||
Your package will now be upgraded to the next tier.
|
||||
|
||||
If you have any questions or require additional support, please contact us
|
||||
at %3$s.
|
||||
|
||||
Regards,
|
||||
Example Registry
|
||||
|
||||
@@ -23,6 +23,7 @@ import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.SendEmailService;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.Inject;
|
||||
import javax.mail.internet.AddressException;
|
||||
@@ -54,8 +55,9 @@ public class SendEmailUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an email from Nomulus to the registrarChangesNotificationEmailAddresses and the specified
|
||||
* additionalAddresses. Returns true iff sending to at least 1 address was successful.
|
||||
* Sends an email from Nomulus to the registrarChangesNotificationEmailAddresses, the bcc address,
|
||||
* and the specified additionalAddresses. Returns true iff sending to at least 1 address was
|
||||
* successful.
|
||||
*
|
||||
* <p>This means that if there are no recipients ({@link #hasRecipients} returns false), this will
|
||||
* return false even thought no error happened.
|
||||
@@ -64,7 +66,10 @@ public class SendEmailUtils {
|
||||
* not all) of the recipients had an error.
|
||||
*/
|
||||
public boolean sendEmail(
|
||||
final String subject, String body, ImmutableList<String> additionalAddresses) {
|
||||
final String subject,
|
||||
String body,
|
||||
Optional<String> bcc,
|
||||
ImmutableList<String> additionalAddresses) {
|
||||
try {
|
||||
InternetAddress from =
|
||||
new InternetAddress(
|
||||
@@ -89,13 +94,22 @@ public class SendEmailUtils {
|
||||
if (recipients.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
emailService.sendEmail(
|
||||
EmailMessage.Builder emailMessage =
|
||||
EmailMessage.newBuilder()
|
||||
.setBody(body)
|
||||
.setSubject(subject)
|
||||
.setRecipients(recipients)
|
||||
.setFrom(from)
|
||||
.build());
|
||||
.setFrom(from);
|
||||
if (bcc.isPresent()) {
|
||||
try {
|
||||
InternetAddress bccInternetAddress = new InternetAddress(bcc.get(), true);
|
||||
emailMessage.addBcc(bccInternetAddress);
|
||||
} catch (AddressException e) {
|
||||
logger.atSevere().withCause(e).log(
|
||||
"Could not send email to %s with subject '%s'.", bcc, subject);
|
||||
}
|
||||
}
|
||||
emailService.sendEmail(emailMessage.build());
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
logger.atSevere().withCause(t).log(
|
||||
@@ -105,6 +119,21 @@ public class SendEmailUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an email from Nomulus to the registrarChangesNotificationEmailAddresses and the specified
|
||||
* additionalAddresses. Returns true iff sending to at least 1 address was successful.
|
||||
*
|
||||
* <p>This means that if there are no recipients ({@link #hasRecipients} returns false), this will
|
||||
* return false even thought no error happened.
|
||||
*
|
||||
* <p>This also means that if there are multiple recipients, it will return true even if some (but
|
||||
* not all) of the recipients had an error.
|
||||
*/
|
||||
public boolean sendEmail(
|
||||
final String subject, String body, ImmutableList<String> additionalAddresses) {
|
||||
return sendEmail(subject, body, Optional.empty(), additionalAddresses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an email from Nomulus to the registrarChangesNotificationEmailAddresses.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user