diff --git a/java/google/registry/flows/FlowRunner.java b/java/google/registry/flows/FlowRunner.java index 46c5ca711..2c4d73bf4 100644 --- a/java/google/registry/flows/FlowRunner.java +++ b/java/google/registry/flows/FlowRunner.java @@ -27,6 +27,7 @@ import google.registry.flows.FlowModule.DryRun; import google.registry.flows.FlowModule.InputXml; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.Transactional; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.eppcommon.Trid; import google.registry.model.eppoutput.EppOutput; import google.registry.monitoring.whitebox.EppMetric; @@ -92,7 +93,8 @@ public class FlowRunner { "trid", trid.getServerTransactionId(), "clientId", clientId, "xml", prettyXml, - "xmlBytes", xmlBase64))); + "xmlBytes", xmlBase64, + "icannActivityReportField", extractActivityReportField(flowClass)))); metric.setCommandNameFromFlow(flowClass.getSimpleName()); if (!isTransactional) { metric.incrementAttempts(); @@ -132,4 +134,16 @@ public class FlowRunner { this.output = output; } } + + /** + * Returns the ICANN activity report field for the given flow class, or the empty string if no + * activity report field specification is found. + */ + private static final String extractActivityReportField(Class flowClass) { + ReportingSpec reportingSpec = flowClass.getAnnotation(ReportingSpec.class); + if (reportingSpec != null) { + return reportingSpec.value().getFieldName(); + } + return ""; + } } diff --git a/java/google/registry/flows/annotations/ReportingSpec.java b/java/google/registry/flows/annotations/ReportingSpec.java new file mode 100644 index 000000000..e06969c2a --- /dev/null +++ b/java/google/registry/flows/annotations/ReportingSpec.java @@ -0,0 +1,32 @@ +// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// +// 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 google.registry.flows.annotations; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** Annotation for flow classes to indicate how this flow should be recorded for reporting. */ +@Documented +@Retention(RUNTIME) +@Target(TYPE) +public @interface ReportingSpec { + /** The ICANN activity reporting field to record for this flow. */ + ActivityReportField value(); +} diff --git a/java/google/registry/flows/contact/ContactCheckFlow.java b/java/google/registry/flows/contact/ContactCheckFlow.java index b9c435907..9f924546e 100644 --- a/java/google/registry/flows/contact/ContactCheckFlow.java +++ b/java/google/registry/flows/contact/ContactCheckFlow.java @@ -24,12 +24,14 @@ import google.registry.flows.EppException; import google.registry.flows.ExtensionManager; import google.registry.flows.Flow; import google.registry.flows.FlowModule.ClientId; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.contact.ContactCommand.Check; import google.registry.model.contact.ContactResource; import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppoutput.CheckData.ContactCheck; import google.registry.model.eppoutput.CheckData.ContactCheckData; import google.registry.model.eppoutput.EppResponse; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.util.Clock; import java.util.List; import java.util.Set; @@ -42,6 +44,7 @@ import javax.inject.Inject; * * @error {@link google.registry.flows.exceptions.TooManyResourceChecksException} */ +@ReportingSpec(ActivityReportField.CONTACT_CHECK) public final class ContactCheckFlow implements Flow { @Inject ResourceCommand resourceCommand; diff --git a/java/google/registry/flows/contact/ContactCreateFlow.java b/java/google/registry/flows/contact/ContactCreateFlow.java index 279deda11..a6ff170bc 100644 --- a/java/google/registry/flows/contact/ContactCreateFlow.java +++ b/java/google/registry/flows/contact/ContactCreateFlow.java @@ -28,6 +28,7 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.contact.ContactCommand.Create; import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource.Builder; @@ -39,6 +40,7 @@ import google.registry.model.index.EppResourceIndex; import google.registry.model.index.ForeignKeyIndex; import google.registry.model.ofy.ObjectifyService; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import javax.inject.Inject; import org.joda.time.DateTime; @@ -49,6 +51,7 @@ import org.joda.time.DateTime; * @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException} * @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException} */ +@ReportingSpec(ActivityReportField.CONTACT_CREATE) public final class ContactCreateFlow implements TransactionalFlow { @Inject ResourceCommand resourceCommand; diff --git a/java/google/registry/flows/contact/ContactDeleteFlow.java b/java/google/registry/flows/contact/ContactDeleteFlow.java index 38897215f..ef9f25e57 100644 --- a/java/google/registry/flows/contact/ContactDeleteFlow.java +++ b/java/google/registry/flows/contact/ContactDeleteFlow.java @@ -33,6 +33,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.async.AsyncFlowEnqueuer; import google.registry.model.contact.ContactResource; import google.registry.model.domain.DomainBase; @@ -41,6 +42,7 @@ import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppoutput.EppResponse; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import javax.inject.Inject; import org.joda.time.DateTime; @@ -58,6 +60,7 @@ import org.joda.time.DateTime; * @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException} * @error {@link google.registry.flows.exceptions.ResourceToDeleteIsReferencedException} */ +@ReportingSpec(ActivityReportField.CONTACT_DELETE) public final class ContactDeleteFlow implements TransactionalFlow { private static final ImmutableSet DISALLOWED_STATUSES = ImmutableSet.of( diff --git a/java/google/registry/flows/contact/ContactInfoFlow.java b/java/google/registry/flows/contact/ContactInfoFlow.java index 7328f55fd..1158d204e 100644 --- a/java/google/registry/flows/contact/ContactInfoFlow.java +++ b/java/google/registry/flows/contact/ContactInfoFlow.java @@ -27,11 +27,13 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.Flow; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.contact.ContactInfoData; import google.registry.model.contact.ContactResource; import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppoutput.EppResponse; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.util.Clock; import javax.inject.Inject; import org.joda.time.DateTime; @@ -46,6 +48,7 @@ import org.joda.time.DateTime; * * @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException} */ +@ReportingSpec(ActivityReportField.CONTACT_INFO) public final class ContactInfoFlow implements Flow { @Inject ExtensionManager extensionManager; diff --git a/java/google/registry/flows/contact/ContactTransferApproveFlow.java b/java/google/registry/flows/contact/ContactTransferApproveFlow.java index 6e96a8961..f28b79345 100644 --- a/java/google/registry/flows/contact/ContactTransferApproveFlow.java +++ b/java/google/registry/flows/contact/ContactTransferApproveFlow.java @@ -31,6 +31,7 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.contact.ContactResource; import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.eppcommon.AuthInfo; @@ -38,6 +39,7 @@ import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppoutput.EppResponse; import google.registry.model.poll.PollMessage; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.transfer.TransferStatus; import javax.inject.Inject; import org.joda.time.DateTime; @@ -55,6 +57,7 @@ import org.joda.time.DateTime; * @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException} * @error {@link google.registry.flows.exceptions.NotPendingTransferException} */ +@ReportingSpec(ActivityReportField.CONTACT_TRANSFER_APPROVE) public final class ContactTransferApproveFlow implements TransactionalFlow { @Inject ResourceCommand resourceCommand; diff --git a/java/google/registry/flows/contact/ContactTransferCancelFlow.java b/java/google/registry/flows/contact/ContactTransferCancelFlow.java index 5e1233d68..ede3c1a66 100644 --- a/java/google/registry/flows/contact/ContactTransferCancelFlow.java +++ b/java/google/registry/flows/contact/ContactTransferCancelFlow.java @@ -31,6 +31,7 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.contact.ContactResource; import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.eppcommon.AuthInfo; @@ -38,6 +39,7 @@ import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppoutput.EppResponse; import google.registry.model.poll.PollMessage; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.transfer.TransferStatus; import javax.inject.Inject; import org.joda.time.DateTime; @@ -55,6 +57,7 @@ import org.joda.time.DateTime; * @error {@link google.registry.flows.exceptions.NotPendingTransferException} * @error {@link google.registry.flows.exceptions.NotTransferInitiatorException} */ +@ReportingSpec(ActivityReportField.CONTACT_TRANSFER_CANCEL) public final class ContactTransferCancelFlow implements TransactionalFlow { @Inject ResourceCommand resourceCommand; diff --git a/java/google/registry/flows/contact/ContactTransferQueryFlow.java b/java/google/registry/flows/contact/ContactTransferQueryFlow.java index 39d1e29f2..6470fe43e 100644 --- a/java/google/registry/flows/contact/ContactTransferQueryFlow.java +++ b/java/google/registry/flows/contact/ContactTransferQueryFlow.java @@ -25,11 +25,13 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.Flow; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.exceptions.NoTransferHistoryToQueryException; import google.registry.flows.exceptions.NotAuthorizedToViewTransferException; import google.registry.model.contact.ContactResource; import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppoutput.EppResponse; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.util.Clock; import javax.inject.Inject; @@ -48,6 +50,7 @@ import javax.inject.Inject; * @error {@link google.registry.flows.exceptions.NoTransferHistoryToQueryException} * @error {@link google.registry.flows.exceptions.NotAuthorizedToViewTransferException} */ +@ReportingSpec(ActivityReportField.CONTACT_TRANSFER_QUERY) public final class ContactTransferQueryFlow implements Flow { @Inject ExtensionManager extensionManager; diff --git a/java/google/registry/flows/contact/ContactTransferRejectFlow.java b/java/google/registry/flows/contact/ContactTransferRejectFlow.java index e1f0a082e..cf945d6c8 100644 --- a/java/google/registry/flows/contact/ContactTransferRejectFlow.java +++ b/java/google/registry/flows/contact/ContactTransferRejectFlow.java @@ -31,12 +31,14 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.contact.ContactResource; import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppoutput.EppResponse; import google.registry.model.poll.PollMessage; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.transfer.TransferStatus; import javax.inject.Inject; import org.joda.time.DateTime; @@ -54,6 +56,7 @@ import org.joda.time.DateTime; * @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} * @error {@link google.registry.flows.exceptions.NotPendingTransferException} */ +@ReportingSpec(ActivityReportField.CONTACT_TRANSFER_REJECT) public final class ContactTransferRejectFlow implements TransactionalFlow { @Inject ExtensionManager extensionManager; diff --git a/java/google/registry/flows/contact/ContactTransferRequestFlow.java b/java/google/registry/flows/contact/ContactTransferRequestFlow.java index 6c1fc3308..a76298e6c 100644 --- a/java/google/registry/flows/contact/ContactTransferRequestFlow.java +++ b/java/google/registry/flows/contact/ContactTransferRequestFlow.java @@ -34,6 +34,7 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.exceptions.AlreadyPendingTransferException; import google.registry.flows.exceptions.ObjectAlreadySponsoredException; import google.registry.model.contact.ContactResource; @@ -44,6 +45,7 @@ import google.registry.model.eppcommon.Trid; import google.registry.model.eppoutput.EppResponse; import google.registry.model.poll.PollMessage; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferStatus; import javax.inject.Inject; @@ -66,6 +68,7 @@ import org.joda.time.Duration; * @error {@link google.registry.flows.exceptions.ObjectAlreadySponsoredException} * @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException} */ +@ReportingSpec(ActivityReportField.CONTACT_TRANSFER_REQUEST) public final class ContactTransferRequestFlow implements TransactionalFlow { private static final ImmutableSet DISALLOWED_STATUSES = ImmutableSet.of( diff --git a/java/google/registry/flows/contact/ContactUpdateFlow.java b/java/google/registry/flows/contact/ContactUpdateFlow.java index 7422e5e16..bb797a59d 100644 --- a/java/google/registry/flows/contact/ContactUpdateFlow.java +++ b/java/google/registry/flows/contact/ContactUpdateFlow.java @@ -35,6 +35,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException; import google.registry.model.contact.ContactCommand.Update; import google.registry.model.contact.ContactCommand.Update.Change; @@ -47,6 +48,7 @@ import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppoutput.EppResponse; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import javax.annotation.Nullable; import javax.inject.Inject; import org.joda.time.DateTime; @@ -63,6 +65,7 @@ import org.joda.time.DateTime; * @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException} * @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException} */ +@ReportingSpec(ActivityReportField.CONTACT_UPDATE) public final class ContactUpdateFlow implements TransactionalFlow { /** diff --git a/java/google/registry/flows/domain/ClaimsCheckFlow.java b/java/google/registry/flows/domain/ClaimsCheckFlow.java index c40e9812d..a80682d83 100644 --- a/java/google/registry/flows/domain/ClaimsCheckFlow.java +++ b/java/google/registry/flows/domain/ClaimsCheckFlow.java @@ -33,6 +33,7 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.Flow; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.domain.DomainCommand.Check; import google.registry.model.domain.launch.LaunchCheckExtension; import google.registry.model.domain.launch.LaunchCheckResponseExtension; @@ -42,6 +43,7 @@ import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppoutput.EppResponse; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.tmch.ClaimsListShard; import google.registry.util.Clock; import java.util.HashSet; @@ -60,6 +62,7 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.TldDoesNotExistException} * @error {@link ClaimsCheckNotAllowedInSunrise} */ +@ReportingSpec(ActivityReportField.DOMAIN_CHECK) // Claims check is a special domain check. public final class ClaimsCheckFlow implements Flow { @Inject ExtensionManager extensionManager; diff --git a/java/google/registry/flows/domain/DomainAllocateFlow.java b/java/google/registry/flows/domain/DomainAllocateFlow.java index a89b8ca34..1929f231e 100644 --- a/java/google/registry/flows/domain/DomainAllocateFlow.java +++ b/java/google/registry/flows/domain/DomainAllocateFlow.java @@ -53,6 +53,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.domain.DomainFlowUtils.DomainNotAllowedForTldWithCreateRestrictionException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForNameserverRestrictedDomainException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException; @@ -87,6 +88,7 @@ import google.registry.model.poll.PollMessage; import google.registry.model.registry.Registry; import google.registry.model.registry.label.ReservationType; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.tmch.LordnTask; import java.util.Set; import javax.inject.Inject; @@ -107,6 +109,7 @@ import org.joda.time.DateTime; * @error {@link NameserversNotSpecifiedForNameserverRestrictedDomainException} * @error {@link NameserversNotSpecifiedForTldWithNameserverWhitelistException} */ +@ReportingSpec(ActivityReportField.DOMAIN_CREATE) // Allocates are special domain creates. public class DomainAllocateFlow implements TransactionalFlow { private static final String COLLISION_MESSAGE = diff --git a/java/google/registry/flows/domain/DomainApplicationCreateFlow.java b/java/google/registry/flows/domain/DomainApplicationCreateFlow.java index 729af9dc9..db29303c6 100644 --- a/java/google/registry/flows/domain/DomainApplicationCreateFlow.java +++ b/java/google/registry/flows/domain/DomainApplicationCreateFlow.java @@ -58,6 +58,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.custom.DomainApplicationCreateFlowCustomLogic; import google.registry.flows.custom.DomainApplicationCreateFlowCustomLogic.AfterValidationParameters; import google.registry.flows.custom.DomainApplicationCreateFlowCustomLogic.BeforeResponseParameters; @@ -93,6 +94,7 @@ import google.registry.model.ofy.ObjectifyService; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.smd.AbstractSignedMark; import google.registry.model.smd.EncodedSignedMark; import javax.inject.Inject; @@ -166,6 +168,7 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} * @error {@link DomainFlowUtils.UnsupportedMarkTypeException} */ +@ReportingSpec(ActivityReportField.DOMAIN_CREATE) // Applications are technically domains in EPP. public final class DomainApplicationCreateFlow implements TransactionalFlow { @Inject ExtensionManager extensionManager; diff --git a/java/google/registry/flows/domain/DomainApplicationDeleteFlow.java b/java/google/registry/flows/domain/DomainApplicationDeleteFlow.java index e7290b88f..05b379527 100644 --- a/java/google/registry/flows/domain/DomainApplicationDeleteFlow.java +++ b/java/google/registry/flows/domain/DomainApplicationDeleteFlow.java @@ -36,6 +36,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.domain.DomainApplication; import google.registry.model.domain.launch.LaunchDeleteExtension; import google.registry.model.domain.launch.LaunchPhase; @@ -46,6 +47,7 @@ import google.registry.model.eppoutput.EppResponse; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import javax.inject.Inject; import org.joda.time.DateTime; @@ -61,6 +63,7 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.LaunchPhaseMismatchException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException} */ +@ReportingSpec(ActivityReportField.DOMAIN_DELETE) // Applications are technically domains in EPP. public final class DomainApplicationDeleteFlow implements TransactionalFlow { @Inject ExtensionManager extensionManager; diff --git a/java/google/registry/flows/domain/DomainApplicationInfoFlow.java b/java/google/registry/flows/domain/DomainApplicationInfoFlow.java index 41e4e50cc..acc361b1c 100644 --- a/java/google/registry/flows/domain/DomainApplicationInfoFlow.java +++ b/java/google/registry/flows/domain/DomainApplicationInfoFlow.java @@ -36,6 +36,7 @@ import google.registry.flows.Flow; import google.registry.flows.FlowModule.ApplicationId; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.domain.DomainApplication; import google.registry.model.domain.DomainCommand.Info; import google.registry.model.domain.DomainInfoData; @@ -47,6 +48,7 @@ import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppoutput.EppResponse; import google.registry.model.eppoutput.EppResponse.ResponseExtension; import google.registry.model.mark.Mark; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.smd.EncodedSignedMark; import google.registry.model.smd.SignedMark; import google.registry.util.Clock; @@ -64,6 +66,7 @@ import javax.inject.Inject; * @error {@link DomainApplicationInfoFlow.ApplicationLaunchPhaseMismatchException} * @error {@link MissingApplicationIdException} */ +@ReportingSpec(ActivityReportField.DOMAIN_INFO) // Applications are technically domains in EPP. public final class DomainApplicationInfoFlow implements Flow { @Inject ResourceCommand resourceCommand; diff --git a/java/google/registry/flows/domain/DomainApplicationUpdateFlow.java b/java/google/registry/flows/domain/DomainApplicationUpdateFlow.java index dd5e5fa89..3662da025 100644 --- a/java/google/registry/flows/domain/DomainApplicationUpdateFlow.java +++ b/java/google/registry/flows/domain/DomainApplicationUpdateFlow.java @@ -58,6 +58,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForNonFreeOperationException; import google.registry.model.ImmutableObject; import google.registry.model.domain.DomainApplication; @@ -76,6 +77,7 @@ import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppoutput.EppResponse; import google.registry.model.registry.Registry; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import javax.inject.Inject; import org.joda.time.DateTime; @@ -114,6 +116,7 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.UrgentAttributeNotSupportedException} * @error {@link DomainApplicationUpdateFlow.ApplicationStatusProhibitsUpdateException} */ +@ReportingSpec(ActivityReportField.DOMAIN_UPDATE) // Applications are technically domains in EPP. public class DomainApplicationUpdateFlow implements TransactionalFlow { /** diff --git a/java/google/registry/flows/domain/DomainCheckFlow.java b/java/google/registry/flows/domain/DomainCheckFlow.java index 858ff710f..efad7081a 100644 --- a/java/google/registry/flows/domain/DomainCheckFlow.java +++ b/java/google/registry/flows/domain/DomainCheckFlow.java @@ -42,6 +42,7 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.Flow; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.custom.DomainCheckFlowCustomLogic; import google.registry.flows.custom.DomainCheckFlowCustomLogic.BeforeResponseParameters; import google.registry.flows.custom.DomainCheckFlowCustomLogic.BeforeResponseReturnData; @@ -61,6 +62,7 @@ import google.registry.model.eppoutput.EppResponse.ResponseExtension; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; import google.registry.model.registry.label.ReservationType; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.util.Clock; import java.util.HashSet; import java.util.List; @@ -94,6 +96,7 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.UnknownFeeCommandException} * @error {@link OnlyCheckedNamesCanBeFeeCheckedException} */ +@ReportingSpec(ActivityReportField.DOMAIN_CHECK) public final class DomainCheckFlow implements Flow { /** diff --git a/java/google/registry/flows/domain/DomainCreateFlow.java b/java/google/registry/flows/domain/DomainCreateFlow.java index e5f238329..8ea665ccc 100644 --- a/java/google/registry/flows/domain/DomainCreateFlow.java +++ b/java/google/registry/flows/domain/DomainCreateFlow.java @@ -58,6 +58,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.custom.DomainCreateFlowCustomLogic; import google.registry.flows.custom.DomainCreateFlowCustomLogic.BeforeResponseParameters; import google.registry.flows.custom.DomainCreateFlowCustomLogic.BeforeResponseReturnData; @@ -95,6 +96,7 @@ import google.registry.model.poll.PollMessage.Autorenew; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.tmch.LordnTask; import javax.inject.Inject; import org.joda.time.DateTime; @@ -155,6 +157,7 @@ import org.joda.time.DateTime; * @error {@link DomainCreateFlow.DomainHasOpenApplicationsException} * @error {@link DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException} */ +@ReportingSpec(ActivityReportField.DOMAIN_CREATE) public class DomainCreateFlow implements TransactionalFlow { private static final ImmutableSet SUNRISE_STATES = diff --git a/java/google/registry/flows/domain/DomainDeleteFlow.java b/java/google/registry/flows/domain/DomainDeleteFlow.java index 448a0a96c..ad95c988d 100644 --- a/java/google/registry/flows/domain/DomainDeleteFlow.java +++ b/java/google/registry/flows/domain/DomainDeleteFlow.java @@ -46,6 +46,7 @@ import google.registry.flows.FlowModule.TargetId; import google.registry.flows.ResourceFlowUtils; import google.registry.flows.SessionMetadata; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.custom.DomainDeleteFlowCustomLogic; import google.registry.flows.custom.DomainDeleteFlowCustomLogic.AfterValidationParameters; import google.registry.flows.custom.DomainDeleteFlowCustomLogic.BeforeResponseParameters; @@ -77,6 +78,7 @@ import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage.OneTime; import google.registry.model.registry.Registry; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.transfer.TransferStatus; import java.util.Set; import javax.annotation.Nullable; @@ -95,6 +97,7 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.BadCommandForRegistryPhaseException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException} */ +@ReportingSpec(ActivityReportField.DOMAIN_DELETE) public final class DomainDeleteFlow implements TransactionalFlow { private static final ImmutableSet DISALLOWED_STATUSES = ImmutableSet.of( diff --git a/java/google/registry/flows/domain/DomainInfoFlow.java b/java/google/registry/flows/domain/DomainInfoFlow.java index e431f001b..b2d4c717d 100644 --- a/java/google/registry/flows/domain/DomainInfoFlow.java +++ b/java/google/registry/flows/domain/DomainInfoFlow.java @@ -32,6 +32,7 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.Flow; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.custom.DomainInfoFlowCustomLogic; import google.registry.flows.custom.DomainInfoFlowCustomLogic.AfterValidationParameters; import google.registry.flows.custom.DomainInfoFlowCustomLogic.BeforeResponseParameters; @@ -49,6 +50,7 @@ import google.registry.model.eppinput.EppInput; import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppoutput.EppResponse; import google.registry.model.eppoutput.EppResponse.ResponseExtension; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.util.Clock; import javax.inject.Inject; import org.joda.time.DateTime; @@ -68,6 +70,7 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.RestoresAreAlwaysForOneYearException} * @error {@link DomainFlowUtils.TransfersAreAlwaysForOneYearException} */ +@ReportingSpec(ActivityReportField.DOMAIN_INFO) public final class DomainInfoFlow implements Flow { @Inject ExtensionManager extensionManager; diff --git a/java/google/registry/flows/domain/DomainRenewFlow.java b/java/google/registry/flows/domain/DomainRenewFlow.java index b4ef74d86..b6033ade2 100644 --- a/java/google/registry/flows/domain/DomainRenewFlow.java +++ b/java/google/registry/flows/domain/DomainRenewFlow.java @@ -41,6 +41,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.custom.DomainRenewFlowCustomLogic; import google.registry.flows.custom.DomainRenewFlowCustomLogic.AfterValidationParameters; import google.registry.flows.custom.DomainRenewFlowCustomLogic.BeforeResponseParameters; @@ -69,6 +70,7 @@ import google.registry.model.eppoutput.EppResponse; import google.registry.model.poll.PollMessage; import google.registry.model.registry.Registry; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import javax.inject.Inject; import org.joda.money.Money; import org.joda.time.DateTime; @@ -99,6 +101,7 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} * @error {@link DomainRenewFlow.IncorrectCurrentExpirationDateException} */ +@ReportingSpec(ActivityReportField.DOMAIN_RENEW) public final class DomainRenewFlow implements TransactionalFlow { private static final ImmutableSet RENEW_DISALLOWED_STATUSES = ImmutableSet.of( diff --git a/java/google/registry/flows/domain/DomainRestoreRequestFlow.java b/java/google/registry/flows/domain/DomainRestoreRequestFlow.java index 2abfe1d5b..ec6ea350c 100644 --- a/java/google/registry/flows/domain/DomainRestoreRequestFlow.java +++ b/java/google/registry/flows/domain/DomainRestoreRequestFlow.java @@ -42,6 +42,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.ImmutableObject; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent.OneTime; @@ -63,6 +64,7 @@ import google.registry.model.eppoutput.EppResponse; import google.registry.model.poll.PollMessage; import google.registry.model.registry.Registry; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import javax.inject.Inject; import org.joda.money.Money; import org.joda.time.DateTime; @@ -101,6 +103,7 @@ import org.joda.time.DateTime; * @error {@link DomainRestoreRequestFlow.DomainNotEligibleForRestoreException} * @error {@link DomainRestoreRequestFlow.RestoreCommandIncludesChangesException} */ +@ReportingSpec(ActivityReportField.DOMAIN_RGP_RESTORE_REQUEST) public final class DomainRestoreRequestFlow implements TransactionalFlow { @Inject ResourceCommand resourceCommand; diff --git a/java/google/registry/flows/domain/DomainTransferApproveFlow.java b/java/google/registry/flows/domain/DomainTransferApproveFlow.java index 304f4450c..ddd210e3a 100644 --- a/java/google/registry/flows/domain/DomainTransferApproveFlow.java +++ b/java/google/registry/flows/domain/DomainTransferApproveFlow.java @@ -38,6 +38,7 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.ImmutableObject; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent.Flag; @@ -51,6 +52,7 @@ import google.registry.model.eppoutput.EppResponse; import google.registry.model.poll.PollMessage; import google.registry.model.registry.Registry; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferStatus; import javax.inject.Inject; @@ -74,6 +76,7 @@ import org.joda.time.DateTime; * @error {@link google.registry.flows.exceptions.NotPendingTransferException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException} */ +@ReportingSpec(ActivityReportField.DOMAIN_TRANSFER_APPROVE) public final class DomainTransferApproveFlow implements TransactionalFlow { @Inject ExtensionManager extensionManager; diff --git a/java/google/registry/flows/domain/DomainTransferCancelFlow.java b/java/google/registry/flows/domain/DomainTransferCancelFlow.java index 162ae544b..6a0874faf 100644 --- a/java/google/registry/flows/domain/DomainTransferCancelFlow.java +++ b/java/google/registry/flows/domain/DomainTransferCancelFlow.java @@ -34,12 +34,14 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.ImmutableObject; import google.registry.model.domain.DomainResource; import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppoutput.EppResponse; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.transfer.TransferStatus; import javax.inject.Inject; import org.joda.time.DateTime; @@ -62,6 +64,7 @@ import org.joda.time.DateTime; * @error {@link google.registry.flows.exceptions.NotTransferInitiatorException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException} */ +@ReportingSpec(ActivityReportField.DOMAIN_TRANSFER_CANCEL) public final class DomainTransferCancelFlow implements TransactionalFlow { @Inject ExtensionManager extensionManager; diff --git a/java/google/registry/flows/domain/DomainTransferQueryFlow.java b/java/google/registry/flows/domain/DomainTransferQueryFlow.java index ff214c65f..6afa9454c 100644 --- a/java/google/registry/flows/domain/DomainTransferQueryFlow.java +++ b/java/google/registry/flows/domain/DomainTransferQueryFlow.java @@ -26,11 +26,13 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.Flow; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.exceptions.NoTransferHistoryToQueryException; import google.registry.flows.exceptions.NotAuthorizedToViewTransferException; import google.registry.model.domain.DomainResource; import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppoutput.EppResponse; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferStatus; import google.registry.util.Clock; @@ -52,6 +54,7 @@ import org.joda.time.DateTime; * @error {@link google.registry.flows.exceptions.NoTransferHistoryToQueryException} * @error {@link google.registry.flows.exceptions.NotAuthorizedToViewTransferException} */ +@ReportingSpec(ActivityReportField.DOMAIN_TRANSFER_QUERY) public final class DomainTransferQueryFlow implements Flow { @Inject ExtensionManager extensionManager; diff --git a/java/google/registry/flows/domain/DomainTransferRejectFlow.java b/java/google/registry/flows/domain/DomainTransferRejectFlow.java index 6028ebb64..f776b7dd0 100644 --- a/java/google/registry/flows/domain/DomainTransferRejectFlow.java +++ b/java/google/registry/flows/domain/DomainTransferRejectFlow.java @@ -34,12 +34,14 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.ImmutableObject; import google.registry.model.domain.DomainResource; import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppoutput.EppResponse; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.transfer.TransferStatus; import javax.inject.Inject; import org.joda.time.DateTime; @@ -62,6 +64,7 @@ import org.joda.time.DateTime; * @error {@link google.registry.flows.exceptions.NotPendingTransferException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException} */ +@ReportingSpec(ActivityReportField.DOMAIN_TRANSFER_REJECT) public final class DomainTransferRejectFlow implements TransactionalFlow { @Inject ExtensionManager extensionManager; diff --git a/java/google/registry/flows/domain/DomainTransferRequestFlow.java b/java/google/registry/flows/domain/DomainTransferRequestFlow.java index 5c93d550a..0e9e78df3 100644 --- a/java/google/registry/flows/domain/DomainTransferRequestFlow.java +++ b/java/google/registry/flows/domain/DomainTransferRequestFlow.java @@ -42,6 +42,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.exceptions.AlreadyPendingTransferException; import google.registry.flows.exceptions.ObjectAlreadySponsoredException; import google.registry.flows.exceptions.TransferPeriodMustBeOneYearException; @@ -61,6 +62,7 @@ import google.registry.model.eppoutput.EppResponse; import google.registry.model.poll.PollMessage; import google.registry.model.registry.Registry; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferData.Builder; import google.registry.model.transfer.TransferData.TransferServerApproveEntity; @@ -100,6 +102,7 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.PremiumNameBlockedException} * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} */ +@ReportingSpec(ActivityReportField.DOMAIN_TRANSFER_REQUEST) public final class DomainTransferRequestFlow implements TransactionalFlow { private static final ImmutableSet DISALLOWED_STATUSES = ImmutableSet.of( diff --git a/java/google/registry/flows/domain/DomainUpdateFlow.java b/java/google/registry/flows/domain/DomainUpdateFlow.java index 961b2fd06..6a05a2ac0 100644 --- a/java/google/registry/flows/domain/DomainUpdateFlow.java +++ b/java/google/registry/flows/domain/DomainUpdateFlow.java @@ -55,6 +55,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.custom.DomainUpdateFlowCustomLogic; import google.registry.flows.custom.DomainUpdateFlowCustomLogic.AfterValidationParameters; import google.registry.flows.custom.DomainUpdateFlowCustomLogic.BeforeSaveParameters; @@ -80,6 +81,7 @@ import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppoutput.EppResponse; import google.registry.model.registry.Registry; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import javax.inject.Inject; import org.joda.time.DateTime; @@ -129,6 +131,7 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.TooManyNameserversException} * @error {@link DomainFlowUtils.UrgentAttributeNotSupportedException} */ +@ReportingSpec(ActivityReportField.DOMAIN_UPDATE) public final class DomainUpdateFlow implements TransactionalFlow { /** diff --git a/java/google/registry/flows/host/HostCheckFlow.java b/java/google/registry/flows/host/HostCheckFlow.java index 0075fd464..b7e089fe0 100644 --- a/java/google/registry/flows/host/HostCheckFlow.java +++ b/java/google/registry/flows/host/HostCheckFlow.java @@ -24,12 +24,14 @@ import google.registry.flows.EppException; import google.registry.flows.ExtensionManager; import google.registry.flows.Flow; import google.registry.flows.FlowModule.ClientId; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppoutput.CheckData.HostCheck; import google.registry.model.eppoutput.CheckData.HostCheckData; import google.registry.model.eppoutput.EppResponse; import google.registry.model.host.HostCommand.Check; import google.registry.model.host.HostResource; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.util.Clock; import java.util.List; import java.util.Set; @@ -42,6 +44,7 @@ import javax.inject.Inject; * * @error {@link google.registry.flows.exceptions.TooManyResourceChecksException} */ +@ReportingSpec(ActivityReportField.HOST_CHECK) public final class HostCheckFlow implements Flow { @Inject ResourceCommand resourceCommand; diff --git a/java/google/registry/flows/host/HostCreateFlow.java b/java/google/registry/flows/host/HostCreateFlow.java index 09a0330a4..9eed8a911 100644 --- a/java/google/registry/flows/host/HostCreateFlow.java +++ b/java/google/registry/flows/host/HostCreateFlow.java @@ -36,6 +36,7 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.ImmutableObject; import google.registry.model.domain.DomainResource; import google.registry.model.domain.metadata.MetadataExtension; @@ -49,6 +50,7 @@ import google.registry.model.index.EppResourceIndex; import google.registry.model.index.ForeignKeyIndex; import google.registry.model.ofy.ObjectifyService; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import javax.inject.Inject; import org.joda.time.DateTime; @@ -73,6 +75,7 @@ import org.joda.time.DateTime; * @error {@link SubordinateHostMustHaveIpException} * @error {@link UnexpectedExternalHostIpException} */ +@ReportingSpec(ActivityReportField.HOST_CREATE) public final class HostCreateFlow implements TransactionalFlow { @Inject ResourceCommand resourceCommand; diff --git a/java/google/registry/flows/host/HostDeleteFlow.java b/java/google/registry/flows/host/HostDeleteFlow.java index 864771b02..20abd05c7 100644 --- a/java/google/registry/flows/host/HostDeleteFlow.java +++ b/java/google/registry/flows/host/HostDeleteFlow.java @@ -32,6 +32,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.async.AsyncFlowEnqueuer; import google.registry.model.EppResource; import google.registry.model.domain.DomainBase; @@ -40,6 +41,7 @@ import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppoutput.EppResponse; import google.registry.model.host.HostResource; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import javax.inject.Inject; import org.joda.time.DateTime; @@ -60,6 +62,7 @@ import org.joda.time.DateTime; * @error {@link HostFlowUtils.HostNameNotNormalizedException} * @error {@link HostFlowUtils.HostNameNotPunyCodedException} */ +@ReportingSpec(ActivityReportField.HOST_DELETE) public final class HostDeleteFlow implements TransactionalFlow { private static final ImmutableSet DISALLOWED_STATUSES = ImmutableSet.of( diff --git a/java/google/registry/flows/host/HostInfoFlow.java b/java/google/registry/flows/host/HostInfoFlow.java index e5b3d5fb6..6750f0fca 100644 --- a/java/google/registry/flows/host/HostInfoFlow.java +++ b/java/google/registry/flows/host/HostInfoFlow.java @@ -27,12 +27,14 @@ import google.registry.flows.ExtensionManager; import google.registry.flows.Flow; import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.TargetId; +import google.registry.flows.annotations.ReportingSpec; import google.registry.model.domain.DomainResource; import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppoutput.EppResponse; import google.registry.model.host.HostInfoData; import google.registry.model.host.HostInfoData.Builder; import google.registry.model.host.HostResource; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.util.Clock; import javax.inject.Inject; import org.joda.time.DateTime; @@ -48,6 +50,7 @@ import org.joda.time.DateTime; * @error {@link HostFlowUtils.HostNameNotNormalizedException} * @error {@link HostFlowUtils.HostNameNotPunyCodedException} */ +@ReportingSpec(ActivityReportField.HOST_INFO) public final class HostInfoFlow implements Flow { @Inject ExtensionManager extensionManager; diff --git a/java/google/registry/flows/host/HostUpdateFlow.java b/java/google/registry/flows/host/HostUpdateFlow.java index 228ebd835..1b3c2c1b4 100644 --- a/java/google/registry/flows/host/HostUpdateFlow.java +++ b/java/google/registry/flows/host/HostUpdateFlow.java @@ -42,6 +42,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.async.AsyncFlowEnqueuer; import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException; import google.registry.model.EppResource; @@ -57,6 +58,7 @@ import google.registry.model.host.HostCommand.Update.Change; import google.registry.model.host.HostResource; import google.registry.model.index.ForeignKeyIndex; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import java.util.Objects; import javax.inject.Inject; import org.joda.time.DateTime; @@ -94,6 +96,7 @@ import org.joda.time.DateTime; * @error {@link HostAlreadyExistsException} * @error {@link RenameHostToExternalRemoveIpException} */ +@ReportingSpec(ActivityReportField.HOST_UPDATE) public final class HostUpdateFlow implements TransactionalFlow { /** diff --git a/java/google/registry/model/reporting/IcannReportingTypes.java b/java/google/registry/model/reporting/IcannReportingTypes.java new file mode 100644 index 000000000..b56f86916 --- /dev/null +++ b/java/google/registry/model/reporting/IcannReportingTypes.java @@ -0,0 +1,69 @@ +// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// +// 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 google.registry.model.reporting; + +/** Types used for ICANN reporting. */ +public final class IcannReportingTypes { + private IcannReportingTypes() {} + + /** + * Represents the set of possible ICANN Monthly Registry Functions Activity Report fields. + * + *

Refer to the \n", - // Base64-encoding of "": - "xmlBytes", "PHhtbC8+"); - } - @Test public void testRun_nonTransactionalCommand_incrementsMetricAttempts() throws Exception { flowRunner.run(); @@ -123,6 +121,31 @@ public class FlowRunnerTest extends ShardableTestCase { assertThat(flowRunner.metric.build().getCommandName()).hasValue("TestCommand"); } + @Test + public void testRun_reportingLogStatement_basic() throws Exception { + flowRunner.run(); + assertThat(parseJsonMap(findLogMessageByPrefix(handler, "EPP-REPORTING-LOG-SIGNATURE: "))) + .containsExactly( + "trid", "server-456", + "clientId", "TheRegistrar", + "xml", "\n", + "xmlBytes", "PHhtbC8+", // Base64-encoding of "". + "icannActivityReportField", ""); + } + + @Test + public void testRun_reportingLogStatement_withReportingSpec() throws Exception { + flowRunner.flowClass = TestReportingSpecCommandFlow.class; + flowRunner.run(); + assertThat(parseJsonMap(findLogMessageByPrefix(handler, "EPP-REPORTING-LOG-SIGNATURE: "))) + .containsExactly( + "trid", "server-456", + "clientId", "TheRegistrar", + "xml", "\n", + "xmlBytes", "PHhtbC8+", // Base64-encoding of "". + "icannActivityReportField", "srs-cont-check"); + } + @Test public void testRun_reportingLogStatement_noClientId() throws Exception { flowRunner.clientId = ""; @@ -132,8 +155,8 @@ public class FlowRunnerTest extends ShardableTestCase { "trid", "server-456", "clientId", "", "xml", "\n", - // Base64-encoding of "": - "xmlBytes", "PHhtbC8+"); + "xmlBytes", "PHhtbC8+", // Base64-encoding of "". + "icannActivityReportField", ""); } @Test @@ -147,7 +170,8 @@ public class FlowRunnerTest extends ShardableTestCase { "trid", "server-456", "clientId", "TheRegistrar", "xml", domainCreateXml, - "xmlBytes", base64().encode(domainCreateXml.getBytes(UTF_8))); + "xmlBytes", base64().encode(domainCreateXml.getBytes(UTF_8)), + "icannActivityReportField", ""); } @Test diff --git a/javatests/google/registry/flows/ResourceFlowTestCase.java b/javatests/google/registry/flows/ResourceFlowTestCase.java index eb4cbf6c9..7b8b0748d 100644 --- a/javatests/google/registry/flows/ResourceFlowTestCase.java +++ b/javatests/google/registry/flows/ResourceFlowTestCase.java @@ -18,12 +18,14 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.tmch.ClaimsListShardTest.createTestClaimsListShard; +import static google.registry.testing.LogsSubject.assertAboutLogs; import static google.registry.testing.TaskQueueHelper.assertTasksEnqueued; import com.google.common.base.Predicate; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.testing.TestLogHandler; import com.googlecode.objectify.Key; import google.registry.flows.FlowUtils.NotLoggedInException; import google.registry.model.EppResource; @@ -38,8 +40,11 @@ import google.registry.model.tmch.ClaimsListShard.ClaimsListRevision; import google.registry.model.tmch.ClaimsListShard.ClaimsListSingleton; import google.registry.testing.TaskQueueHelper.TaskMatcher; import google.registry.util.TypeUtils.TypeInstantiator; +import java.util.logging.Level; +import java.util.logging.Logger; import org.joda.time.DateTime; import org.joda.time.Duration; +import org.junit.Before; import org.junit.Test; /** @@ -51,6 +56,16 @@ import org.junit.Test; public abstract class ResourceFlowTestCase extends FlowTestCase { + private final TestLogHandler logHandler = new TestLogHandler(); + + @Before + public void beforeResourceFlowTestCase() { + // Attach TestLogHandler to the root logger so it has access to all log messages. + // Note that in theory for assertIcannReportingActivityFieldLogged() below it would suffice to + // attach it only to the FlowRunner logger, but for some reason this doesn't work for all flows. + Logger.getLogger("").addHandler(logHandler); + } + protected R reloadResourceByForeignKey(DateTime now) throws Exception { // Force the session to be cleared so that when we read it back, we read from Datastore and // not from the transaction cache or memcache. @@ -151,4 +166,11 @@ public abstract class ResourceFlowTestCase { return builder.build(); } - public And hasNoLogsAtLevel(Level level) { + public void hasNoLogsAtLevel(Level level) { check() .withFailureMessage("Logs at level %s", level) .that(getMessagesAtLevel(level)) .isEmpty(); - return new And<>(this); } - public And hasLogAtLevelWithMessage(Level level, String message) { + public Which hasLogAtLevelWithMessage(Level level, String message) { + List messagesAtLevel = getMessagesAtLevel(level); check() .withFailureMessage("Logs at level %s", level) - .that(getMessagesAtLevel(level)) + .that(messagesAtLevel) .comparingElementsUsing(CONTAINS_CORRESPONDENCE) .contains(message); - return new And<>(this); + for (String messageCandidate : messagesAtLevel) { + if (messageCandidate.contains(message)) { + return new Which<>(assertThat(messageCandidate) + .named(String.format("log message at %s matching '%s'", level, message))); + } + } + throw new AssertionError("Message check passed yet matching message not found"); } public static DelegatedVerb assertAboutLogs() {