diff --git a/core/src/main/java/google/registry/batch/BatchModule.java b/core/src/main/java/google/registry/batch/BatchModule.java index 521b5573a..4d44b94ae 100644 --- a/core/src/main/java/google/registry/batch/BatchModule.java +++ b/core/src/main/java/google/registry/batch/BatchModule.java @@ -40,7 +40,6 @@ import org.joda.time.DateTime; @Module public class BatchModule { - public static final String PARAM_DRY_RUN = "dryRun"; public static final String PARAM_FAST = "fast"; @Provides @@ -138,10 +137,4 @@ public class BatchModule { static boolean provideIsFast(HttpServletRequest req) { return extractBooleanParameter(req, PARAM_FAST); } - - @Provides - @Parameter(PARAM_DRY_RUN) - static boolean provideIsDryRun(HttpServletRequest req) { - return extractBooleanParameter(req, PARAM_DRY_RUN); - } } diff --git a/core/src/main/java/google/registry/batch/DeleteLoadTestDataAction.java b/core/src/main/java/google/registry/batch/DeleteLoadTestDataAction.java index 623864c8d..7fed9c1a2 100644 --- a/core/src/main/java/google/registry/batch/DeleteLoadTestDataAction.java +++ b/core/src/main/java/google/registry/batch/DeleteLoadTestDataAction.java @@ -16,9 +16,9 @@ package google.registry.batch; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.ImmutableSet.toImmutableSet; -import static google.registry.batch.BatchModule.PARAM_DRY_RUN; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.request.Action.Method.POST; +import static google.registry.request.RequestParameters.PARAM_DRY_RUN; import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.RegistryEnvironment.PRODUCTION; diff --git a/core/src/main/java/google/registry/batch/DeleteProberDataAction.java b/core/src/main/java/google/registry/batch/DeleteProberDataAction.java index d290f6fb3..a2c682f0e 100644 --- a/core/src/main/java/google/registry/batch/DeleteProberDataAction.java +++ b/core/src/main/java/google/registry/batch/DeleteProberDataAction.java @@ -17,12 +17,12 @@ package google.registry.batch; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.ImmutableSet.toImmutableSet; -import static google.registry.batch.BatchModule.PARAM_DRY_RUN; import static google.registry.dns.DnsUtils.requestDomainDnsRefresh; import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_DELETE; import static google.registry.model.tld.Tlds.getTldsOfType; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.request.Action.Method.POST; +import static google.registry.request.RequestParameters.PARAM_DRY_RUN; import static google.registry.request.RequestParameters.PARAM_TLDS; import static google.registry.util.RegistryEnvironment.PRODUCTION; diff --git a/core/src/main/java/google/registry/batch/ExpandBillingRecurrencesAction.java b/core/src/main/java/google/registry/batch/ExpandBillingRecurrencesAction.java index 4082b149f..96112114f 100644 --- a/core/src/main/java/google/registry/batch/ExpandBillingRecurrencesAction.java +++ b/core/src/main/java/google/registry/batch/ExpandBillingRecurrencesAction.java @@ -15,10 +15,10 @@ package google.registry.batch; import static com.google.common.base.Preconditions.checkArgument; -import static google.registry.batch.BatchModule.PARAM_DRY_RUN; import static google.registry.beam.BeamUtils.createJobName; import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; +import static google.registry.request.RequestParameters.PARAM_DRY_RUN; import static google.registry.util.DateTimeUtils.START_OF_TIME; import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import static javax.servlet.http.HttpServletResponse.SC_OK; diff --git a/core/src/main/java/google/registry/batch/WipeOutContactHistoryPiiAction.java b/core/src/main/java/google/registry/batch/WipeOutContactHistoryPiiAction.java index 579a72b2f..29697983c 100644 --- a/core/src/main/java/google/registry/batch/WipeOutContactHistoryPiiAction.java +++ b/core/src/main/java/google/registry/batch/WipeOutContactHistoryPiiAction.java @@ -14,8 +14,8 @@ package google.registry.batch; -import static google.registry.batch.BatchModule.PARAM_DRY_RUN; import static google.registry.beam.BeamUtils.createJobName; +import static google.registry.request.RequestParameters.PARAM_DRY_RUN; import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import static javax.servlet.http.HttpServletResponse.SC_OK; diff --git a/core/src/main/java/google/registry/flows/EppToolAction.java b/core/src/main/java/google/registry/flows/EppToolAction.java index e096f3ae7..217440054 100644 --- a/core/src/main/java/google/registry/flows/EppToolAction.java +++ b/core/src/main/java/google/registry/flows/EppToolAction.java @@ -84,11 +84,5 @@ public class EppToolAction implements Runnable { static String provideClientId(HttpServletRequest req) { return extractRequiredParameter(req, "clientId"); } - - @Provides - @Parameter("dryRun") - static boolean provideIsDryRun(HttpServletRequest req) { - return extractBooleanParameter(req, "dryRun"); - } } } diff --git a/core/src/main/java/google/registry/module/RegistryComponent.java b/core/src/main/java/google/registry/module/RegistryComponent.java new file mode 100644 index 000000000..ad9d6d12c --- /dev/null +++ b/core/src/main/java/google/registry/module/RegistryComponent.java @@ -0,0 +1,108 @@ +// Copyright 2024 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.module; + +import com.google.monitoring.metrics.MetricReporter; +import dagger.Component; +import dagger.Lazy; +import dagger.Module; +import dagger.Provides; +import google.registry.batch.BatchModule; +import google.registry.bigquery.BigqueryModule; +import google.registry.config.CloudTasksUtilsModule; +import google.registry.config.CredentialModule; +import google.registry.config.RegistryConfig.ConfigModule; +import google.registry.dns.writer.VoidDnsWriterModule; +import google.registry.export.DriveModule; +import google.registry.export.sheet.SheetsServiceModule; +import google.registry.flows.ServerTridProviderModule; +import google.registry.flows.custom.CustomLogicFactoryModule; +import google.registry.groups.DirectoryModule; +import google.registry.groups.GmailModule; +import google.registry.groups.GroupsModule; +import google.registry.groups.GroupssettingsModule; +import google.registry.keyring.KeyringModule; +import google.registry.keyring.api.DummyKeyringModule; +import google.registry.keyring.api.KeyModule; +import google.registry.keyring.secretmanager.SecretManagerKeyringModule; +import google.registry.module.RegistryComponent.RegistryModule; +import google.registry.module.RequestComponent.RequestComponentModule; +import google.registry.monitoring.whitebox.StackdriverModule; +import google.registry.persistence.PersistenceModule; +import google.registry.privileges.secretmanager.SecretManagerModule; +import google.registry.rde.JSchModule; +import google.registry.request.Modules.GsonModule; +import google.registry.request.Modules.NetHttpTransportModule; +import google.registry.request.Modules.UrlConnectionServiceModule; +import google.registry.request.Modules.UserServiceModule; +import google.registry.request.RequestHandler; +import google.registry.request.auth.AuthModule; +import google.registry.request.auth.RequestAuthenticator; +import google.registry.ui.ConsoleDebug.ConsoleConfigModule; +import google.registry.util.UtilsModule; +import javax.inject.Provider; +import javax.inject.Singleton; + +/** Dagger component with instance lifetime. */ +@Singleton +@Component( + modules = { + AuthModule.class, + BatchModule.class, + BigqueryModule.class, + CloudTasksUtilsModule.class, + ConfigModule.class, + ConsoleConfigModule.class, + CredentialModule.class, + CustomLogicFactoryModule.class, + DirectoryModule.class, + DriveModule.class, + DummyKeyringModule.class, + GmailModule.class, + GroupsModule.class, + GroupssettingsModule.class, + GsonModule.class, + JSchModule.class, + KeyModule.class, + KeyringModule.class, + NetHttpTransportModule.class, + PersistenceModule.class, + RegistryModule.class, + RequestComponentModule.class, + SecretManagerKeyringModule.class, + SecretManagerModule.class, + ServerTridProviderModule.class, + SheetsServiceModule.class, + StackdriverModule.class, + UrlConnectionServiceModule.class, + UserServiceModule.class, + UtilsModule.class, + VoidDnsWriterModule.class, + }) +interface RegistryComponent { + RequestHandler requestHandler(); + + Lazy metricReporter(); + + @Module + class RegistryModule { + @Provides + static RequestHandler provideRequestHandler( + Provider componentProvider, + RequestAuthenticator requestAuthenticator) { + return RequestHandler.create(RequestComponent.class, componentProvider, requestAuthenticator); + } + } +} diff --git a/core/src/main/java/google/registry/module/RegistryServlet.java b/core/src/main/java/google/registry/module/RegistryServlet.java new file mode 100644 index 000000000..1a3dc3006 --- /dev/null +++ b/core/src/main/java/google/registry/module/RegistryServlet.java @@ -0,0 +1,30 @@ +// Copyright 2024 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.module; + +import com.google.monitoring.metrics.MetricReporter; +import dagger.Lazy; +import google.registry.request.RequestHandler; + +/** Servlet that handles all requests. */ +public class RegistryServlet extends ServletBase { + private static final RegistryComponent component = DaggerRegistryComponent.create(); + private static final RequestHandler requestHandler = component.requestHandler(); + private static final Lazy metricReporter = component.metricReporter(); + + public RegistryServlet() { + super(requestHandler, metricReporter); + } +} diff --git a/core/src/main/java/google/registry/module/RequestComponent.java b/core/src/main/java/google/registry/module/RequestComponent.java new file mode 100644 index 000000000..3765f91e4 --- /dev/null +++ b/core/src/main/java/google/registry/module/RequestComponent.java @@ -0,0 +1,337 @@ +// Copyright 2024 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.module; + +import dagger.Module; +import dagger.Subcomponent; +import google.registry.batch.BatchModule; +import google.registry.batch.CannedScriptExecutionAction; +import google.registry.batch.DeleteExpiredDomainsAction; +import google.registry.batch.DeleteLoadTestDataAction; +import google.registry.batch.DeleteProberDataAction; +import google.registry.batch.ExpandBillingRecurrencesAction; +import google.registry.batch.RelockDomainAction; +import google.registry.batch.ResaveAllEppResourcesPipelineAction; +import google.registry.batch.ResaveEntityAction; +import google.registry.batch.SendExpiringCertificateNotificationEmailAction; +import google.registry.batch.WipeOutContactHistoryPiiAction; +import google.registry.bsa.BsaDownloadAction; +import google.registry.bsa.BsaRefreshAction; +import google.registry.bsa.UploadBsaUnavailableDomainsAction; +import google.registry.cron.CronModule; +import google.registry.cron.TldFanoutAction; +import google.registry.dns.DnsModule; +import google.registry.dns.PublishDnsUpdatesAction; +import google.registry.dns.ReadDnsRefreshRequestsAction; +import google.registry.dns.RefreshDnsAction; +import google.registry.dns.RefreshDnsOnHostRenameAction; +import google.registry.dns.writer.VoidDnsWriterModule; +import google.registry.dns.writer.clouddns.CloudDnsWriterModule; +import google.registry.dns.writer.dnsupdate.DnsUpdateConfigModule; +import google.registry.dns.writer.dnsupdate.DnsUpdateWriterModule; +import google.registry.export.ExportDomainListsAction; +import google.registry.export.ExportPremiumTermsAction; +import google.registry.export.ExportReservedTermsAction; +import google.registry.export.SyncGroupMembersAction; +import google.registry.export.sheet.SheetModule; +import google.registry.export.sheet.SyncRegistrarsSheetAction; +import google.registry.flows.CheckApiAction; +import google.registry.flows.CheckApiAction.CheckApiModule; +import google.registry.flows.EppTlsAction; +import google.registry.flows.EppToolAction; +import google.registry.flows.EppToolAction.EppToolModule; +import google.registry.flows.FlowComponent; +import google.registry.flows.TlsCredentials.EppTlsModule; +import google.registry.flows.custom.CustomLogicModule; +import google.registry.loadtest.LoadTestAction; +import google.registry.loadtest.LoadTestModule; +import google.registry.monitoring.whitebox.WhiteboxModule; +import google.registry.rdap.RdapAutnumAction; +import google.registry.rdap.RdapDomainAction; +import google.registry.rdap.RdapDomainSearchAction; +import google.registry.rdap.RdapEntityAction; +import google.registry.rdap.RdapEntitySearchAction; +import google.registry.rdap.RdapHelpAction; +import google.registry.rdap.RdapIpAction; +import google.registry.rdap.RdapModule; +import google.registry.rdap.RdapNameserverAction; +import google.registry.rdap.RdapNameserverSearchAction; +import google.registry.rdap.UpdateRegistrarRdapBaseUrlsAction; +import google.registry.rde.BrdaCopyAction; +import google.registry.rde.RdeModule; +import google.registry.rde.RdeReportAction; +import google.registry.rde.RdeReporter; +import google.registry.rde.RdeStagingAction; +import google.registry.rde.RdeUploadAction; +import google.registry.reporting.ReportingModule; +import google.registry.reporting.billing.BillingModule; +import google.registry.reporting.billing.CopyDetailReportsAction; +import google.registry.reporting.billing.GenerateInvoicesAction; +import google.registry.reporting.billing.PublishInvoicesAction; +import google.registry.reporting.icann.DnsCountQueryCoordinatorModule; +import google.registry.reporting.icann.IcannReportingModule; +import google.registry.reporting.icann.IcannReportingStagingAction; +import google.registry.reporting.icann.IcannReportingUploadAction; +import google.registry.reporting.spec11.GenerateSpec11ReportAction; +import google.registry.reporting.spec11.PublishSpec11ReportAction; +import google.registry.reporting.spec11.Spec11Module; +import google.registry.request.RequestComponentBuilder; +import google.registry.request.RequestModule; +import google.registry.request.RequestScope; +import google.registry.tmch.NordnUploadAction; +import google.registry.tmch.NordnVerifyAction; +import google.registry.tmch.TmchCrlAction; +import google.registry.tmch.TmchDnlAction; +import google.registry.tmch.TmchModule; +import google.registry.tmch.TmchSmdrlAction; +import google.registry.tools.server.CreateGroupsAction; +import google.registry.tools.server.GenerateZoneFilesAction; +import google.registry.tools.server.ListDomainsAction; +import google.registry.tools.server.ListHostsAction; +import google.registry.tools.server.ListPremiumListsAction; +import google.registry.tools.server.ListRegistrarsAction; +import google.registry.tools.server.ListReservedListsAction; +import google.registry.tools.server.ListTldsAction; +import google.registry.tools.server.RefreshDnsForAllDomainsAction; +import google.registry.tools.server.ToolsServerModule; +import google.registry.tools.server.VerifyOteAction; +import google.registry.ui.server.console.ConsoleDomainGetAction; +import google.registry.ui.server.console.ConsoleDomainListAction; +import google.registry.ui.server.console.ConsoleUserDataAction; +import google.registry.ui.server.console.RegistrarsAction; +import google.registry.ui.server.console.settings.ContactAction; +import google.registry.ui.server.console.settings.SecurityAction; +import google.registry.ui.server.console.settings.WhoisRegistrarFieldsAction; +import google.registry.ui.server.registrar.ConsoleOteSetupAction; +import google.registry.ui.server.registrar.ConsoleRegistrarCreatorAction; +import google.registry.ui.server.registrar.ConsoleUiAction; +import google.registry.ui.server.registrar.OteStatusAction; +import google.registry.ui.server.registrar.RegistrarConsoleModule; +import google.registry.ui.server.registrar.RegistrarSettingsAction; +import google.registry.ui.server.registrar.RegistryLockGetAction; +import google.registry.ui.server.registrar.RegistryLockPostAction; +import google.registry.ui.server.registrar.RegistryLockVerifyAction; +import google.registry.whois.WhoisAction; +import google.registry.whois.WhoisHttpAction; +import google.registry.whois.WhoisModule; + +/** Dagger component with per-request lifetime. */ +@RequestScope +@Subcomponent( + modules = { + BatchModule.class, + BillingModule.class, + CheckApiModule.class, + CloudDnsWriterModule.class, + CronModule.class, + CustomLogicModule.class, + DnsCountQueryCoordinatorModule.class, + DnsModule.class, + DnsUpdateConfigModule.class, + DnsUpdateWriterModule.class, + EppTlsModule.class, + EppToolModule.class, + IcannReportingModule.class, + LoadTestModule.class, + RdapModule.class, + RdeModule.class, + RegistrarConsoleModule.class, + ReportingModule.class, + RequestModule.class, + SheetModule.class, + Spec11Module.class, + TmchModule.class, + ToolsServerModule.class, + VoidDnsWriterModule.class, + WhiteboxModule.class, + WhoisModule.class, + }) +interface RequestComponent { + FlowComponent.Builder flowComponentBuilder(); + + BrdaCopyAction brdaCopyAction(); + + BsaDownloadAction bsaDownloadAction(); + + BsaRefreshAction bsaRefreshAction(); + + CannedScriptExecutionAction cannedScriptExecutionAction(); + + CheckApiAction checkApiAction(); + + ConsoleDomainGetAction consoleDomainGetAction(); + + ConsoleDomainListAction consoleDomainListAction(); + + ConsoleOteSetupAction consoleOteSetupAction(); + + ConsoleRegistrarCreatorAction consoleRegistrarCreatorAction(); + + ConsoleUiAction consoleUiAction(); + + ConsoleUserDataAction consoleUserDataAction(); + + ContactAction contactAction(); + + CopyDetailReportsAction copyDetailReportAction(); + + CreateGroupsAction createGroupsAction(); + + DeleteExpiredDomainsAction deleteExpiredDomainsAction(); + + DeleteLoadTestDataAction deleteLoadTestDataAction(); + + DeleteProberDataAction deleteProberDataAction(); + + EppTlsAction eppTlsAction(); + + EppToolAction eppToolAction(); + + ExpandBillingRecurrencesAction expandBillingRecurrencesAction(); + + ExportDomainListsAction exportDomainListsAction(); + + ExportPremiumTermsAction exportPremiumTermsAction(); + + ExportReservedTermsAction exportReservedTermsAction(); + + GenerateInvoicesAction generateInvoicesAction(); + + GenerateSpec11ReportAction generateSpec11ReportAction(); + + GenerateZoneFilesAction generateZoneFilesAction(); + + IcannReportingStagingAction icannReportingStagingAction(); + + IcannReportingUploadAction icannReportingUploadAction(); + + ListDomainsAction listDomainsAction(); + + ListHostsAction listHostsAction(); + + ListPremiumListsAction listPremiumListsAction(); + + ListRegistrarsAction listRegistrarsAction(); + + ListReservedListsAction listReservedListsAction(); + + ListTldsAction listTldsAction(); + + LoadTestAction loadTestAction(); + + NordnUploadAction nordnUploadAction(); + + NordnVerifyAction nordnVerifyAction(); + + OteStatusAction oteStatusAction(); + + PublishDnsUpdatesAction publishDnsUpdatesAction(); + + PublishInvoicesAction uploadInvoicesAction(); + + PublishSpec11ReportAction publishSpec11ReportAction(); + + RdapAutnumAction rdapAutnumAction(); + + RdapDomainAction rdapDomainAction(); + + RdapDomainSearchAction rdapDomainSearchAction(); + + RdapEntityAction rdapEntityAction(); + + RdapEntitySearchAction rdapEntitySearchAction(); + + RdapHelpAction rdapHelpAction(); + + RdapIpAction rdapDefaultAction(); + + RdapNameserverAction rdapNameserverAction(); + + RdapNameserverSearchAction rdapNameserverSearchAction(); + + RdeReportAction rdeReportAction(); + + RdeReporter rdeReporter(); + + RdeStagingAction rdeStagingAction(); + + RdeUploadAction rdeUploadAction(); + + ReadDnsRefreshRequestsAction readDnsRefreshRequestsAction(); + + RefreshDnsAction refreshDnsAction(); + + RefreshDnsForAllDomainsAction refreshDnsForAllDomainsAction(); + + RefreshDnsOnHostRenameAction refreshDnsOnHostRenameAction(); + + RegistrarSettingsAction registrarSettingsAction(); + + RegistrarsAction registrarsAction(); + + RegistryLockGetAction registryLockGetAction(); + + RegistryLockPostAction registryLockPostAction(); + + RegistryLockVerifyAction registryLockVerifyAction(); + + RelockDomainAction relockDomainAction(); + + ResaveAllEppResourcesPipelineAction resaveAllEppResourcesPipelineAction(); + + ResaveEntityAction resaveEntityAction(); + + SecurityAction securityAction(); + + SendExpiringCertificateNotificationEmailAction sendExpiringCertificateNotificationEmailAction(); + + SyncGroupMembersAction syncGroupMembersAction(); + + SyncRegistrarsSheetAction syncRegistrarsSheetAction(); + + TldFanoutAction tldFanoutAction(); + + TmchCrlAction tmchCrlAction(); + + TmchDnlAction tmchDnlAction(); + + TmchSmdrlAction tmchSmdrlAction(); + + UpdateRegistrarRdapBaseUrlsAction updateRegistrarRdapBaseUrlsAction(); + + UploadBsaUnavailableDomainsAction uploadBsaUnavailableDomains(); + + VerifyOteAction verifyOteAction(); + + WhoisAction whoisAction(); + + WhoisHttpAction whoisHttpAction(); + + WhoisRegistrarFieldsAction whoisRegistrarFieldsAction(); + + WipeOutContactHistoryPiiAction wipeOutContactHistoryPiiAction(); + + @Subcomponent.Builder + abstract class Builder implements RequestComponentBuilder { + @Override + public abstract Builder requestModule(RequestModule requestModule); + + @Override + public abstract RequestComponent build(); + } + + @Module(subcomponents = RequestComponent.class) + static class RequestComponentModule {} +} diff --git a/core/src/main/java/google/registry/request/RequestHandler.java b/core/src/main/java/google/registry/request/RequestHandler.java index 26bddd504..1d4af5300 100644 --- a/core/src/main/java/google/registry/request/RequestHandler.java +++ b/core/src/main/java/google/registry/request/RequestHandler.java @@ -95,7 +95,7 @@ public class RequestHandler { } /** Creates a new RequestHandler with an explicit component class for test purposes. */ - public static RequestHandler createForTest( + public static RequestHandler create( Class component, Provider> requestComponentBuilderProvider, RequestAuthenticator requestAuthenticator) { diff --git a/core/src/main/java/google/registry/request/RequestModule.java b/core/src/main/java/google/registry/request/RequestModule.java index 0699e2644..07b0c4dd0 100644 --- a/core/src/main/java/google/registry/request/RequestModule.java +++ b/core/src/main/java/google/registry/request/RequestModule.java @@ -18,6 +18,8 @@ import static com.google.common.net.MediaType.JSON_UTF_8; import static google.registry.dns.PublishDnsUpdatesAction.CLOUD_TASKS_RETRY_HEADER; import static google.registry.model.tld.Tlds.assertTldExists; import static google.registry.model.tld.Tlds.assertTldsExist; +import static google.registry.request.RequestParameters.PARAM_DRY_RUN; +import static google.registry.request.RequestParameters.extractBooleanParameter; import static google.registry.request.RequestParameters.extractRequiredHeader; import static google.registry.request.RequestParameters.extractRequiredParameter; import static google.registry.request.RequestParameters.extractSetOfParameters; @@ -91,6 +93,12 @@ public final class RequestModule { return tlds; } + @Provides + @Parameter(RequestParameters.PARAM_DRY_RUN) + static boolean provideDryRun(HttpServletRequest req) { + return extractBooleanParameter(req, PARAM_DRY_RUN); + } + @Provides static Response provideResponse(ResponseImpl response) { return response; diff --git a/core/src/main/java/google/registry/request/RequestParameters.java b/core/src/main/java/google/registry/request/RequestParameters.java index a5f2365e0..d9aaa3e8e 100644 --- a/core/src/main/java/google/registry/request/RequestParameters.java +++ b/core/src/main/java/google/registry/request/RequestParameters.java @@ -34,9 +34,13 @@ public final class RequestParameters { /** The standardized request parameter name used by any action taking a tld parameter. */ public static final String PARAM_TLD = "tld"; + /** The standardized request parameter name used by any action taking multiple tld parameters. */ public static final String PARAM_TLDS = "tlds"; + /** The standardized request parameter name used by any action in dry run mode. */ + public static final String PARAM_DRY_RUN = "dryRun"; + /** * Returns first GET or POST parameter associated with {@code name}. * @@ -123,10 +127,10 @@ public final class RequestParameters { *

Both missing parameter and parameter with empty value result in an empty set. * * @param req the request that has the parameter - * @param name the name of the parameter, should be in plural form (e.g. tlds=, not tld=) + * @param name the name of the parameter (should be in plural form. e.g., tlds=, not tld=) */ public static ImmutableSet extractSetOfParameters(HttpServletRequest req, String name) { - // First we make sure the user didn't accidentally try to pass the "set of parameters" as + // First, we make sure the user didn't accidentally try to pass the "set of parameters" as // multiple tld=a&tld=b parameters instead of tld=a,b String[] parameters = req.getParameterValues(name); if (parameters != null && parameters.length > 1) { @@ -160,7 +164,7 @@ public final class RequestParameters { * * @param req the request that has the parameter * @param enumClass the Class of the expected Enum type - * @param name the name of the parameter, should be in plural form (e.g. tlds=, not tld=) + * @param name the name of the parameter (should be in plural form e.g., tlds=, not tld=) * @throws BadRequestException if any of the comma-delimited values of the request parameter named * {@code name} aren't equal to any of the values in {@code enumClass} */ @@ -293,7 +297,7 @@ public final class RequestParameters { /** * Returns first HTTP header associated with {@code name}. * - * @param name case insensitive header name + * @param name case-insensitive header name * @throws BadRequestException if request header is absent or empty */ public static String extractRequiredHeader(HttpServletRequest req, String name) { @@ -307,7 +311,7 @@ public final class RequestParameters { /** * Returns an {@link Optional} of the first HTTP header associated with {@code name}, or empty. * - * @param name case insensitive header name + * @param name case-insensitive header name */ public static Optional extractOptionalHeader(HttpServletRequest req, String name) { return Optional.ofNullable(emptyToNull(req.getHeader(name))); diff --git a/core/src/main/java/google/registry/tools/server/ToolsServerModule.java b/core/src/main/java/google/registry/tools/server/ToolsServerModule.java index 4159e0aa0..898c7c3db 100644 --- a/core/src/main/java/google/registry/tools/server/ToolsServerModule.java +++ b/core/src/main/java/google/registry/tools/server/ToolsServerModule.java @@ -70,12 +70,6 @@ public class ToolsServerModule { return extractRequiredParameter(req, "rawKeys"); } - @Provides - @Parameter("jobId") - String provideJobId(HttpServletRequest req) { - return extractRequiredParameter(req, "jobId"); - } - @Provides @Parameter("batchSize") static Optional provideBatchSize(HttpServletRequest req) { diff --git a/core/src/main/java/google/registry/ui/server/console/ConsoleDomainGetAction.java b/core/src/main/java/google/registry/ui/server/console/ConsoleDomainGetAction.java index b8dbf0940..f9af4fb13 100644 --- a/core/src/main/java/google/registry/ui/server/console/ConsoleDomainGetAction.java +++ b/core/src/main/java/google/registry/ui/server/console/ConsoleDomainGetAction.java @@ -51,7 +51,7 @@ public class ConsoleDomainGetAction implements JsonGetAction { AuthResult authResult, Response response, Gson gson, - @Parameter("domain") String paramDomain) { + @Parameter("consoleDomain") String paramDomain) { this.authResult = authResult; this.response = response; this.gson = gson; diff --git a/core/src/main/java/google/registry/ui/server/registrar/ConsoleOteSetupAction.java b/core/src/main/java/google/registry/ui/server/registrar/ConsoleOteSetupAction.java index a5a43dd7a..25cf0ea27 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/ConsoleOteSetupAction.java +++ b/core/src/main/java/google/registry/ui/server/registrar/ConsoleOteSetupAction.java @@ -75,7 +75,7 @@ public final class ConsoleOteSetupAction extends HtmlAction { StringGenerator passwordGenerator; @Inject - @Parameter("clientId") + @Parameter("consoleClientId") Optional clientId; @Inject diff --git a/core/src/main/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorAction.java b/core/src/main/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorAction.java index bb0cab70f..6048515ab 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorAction.java +++ b/core/src/main/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorAction.java @@ -85,8 +85,15 @@ public final class ConsoleRegistrarCreatorAction extends HtmlAction { @Inject SendEmailUtils sendEmailUtils; @Inject @Named("base58StringGenerator") StringGenerator passwordGenerator; @Inject @Named("digitOnlyStringGenerator") StringGenerator passcodeGenerator; - @Inject @Parameter("clientId") Optional clientId; - @Inject @Parameter("name") Optional name; + + @Inject + @Parameter("consoleClientId") + Optional clientId; + + @Inject + @Parameter("consoleName") + Optional name; + @Inject @Parameter("billingAccount") Optional billingAccount; @Inject @Parameter("ianaId") Optional ianaId; @Inject @Parameter("referralEmail") Optional referralEmail; diff --git a/core/src/main/java/google/registry/ui/server/registrar/ConsoleUiAction.java b/core/src/main/java/google/registry/ui/server/registrar/ConsoleUiAction.java index 7c925abd0..83e0b8d8d 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/ConsoleUiAction.java +++ b/core/src/main/java/google/registry/ui/server/registrar/ConsoleUiAction.java @@ -17,7 +17,6 @@ package google.registry.ui.server.registrar; import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.ADMIN; import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.OWNER; import static google.registry.ui.server.SoyTemplateUtils.CSS_RENAMING_MAP_SUPPLIER; -import static google.registry.ui.server.registrar.RegistrarConsoleModule.PARAM_CLIENT_ID; import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE; @@ -85,7 +84,7 @@ public final class ConsoleUiAction extends HtmlAction { boolean enabled; @Inject - @Parameter(PARAM_CLIENT_ID) + @Parameter("consoleClientId") Optional paramClientId; @Inject diff --git a/core/src/main/java/google/registry/ui/server/registrar/RegistrarConsoleModule.java b/core/src/main/java/google/registry/ui/server/registrar/RegistrarConsoleModule.java index f4215224b..c04b143c3 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/RegistrarConsoleModule.java +++ b/core/src/main/java/google/registry/ui/server/registrar/RegistrarConsoleModule.java @@ -52,13 +52,13 @@ public final class RegistrarConsoleModule { } @Provides - @Parameter(PARAM_CLIENT_ID) + @Parameter("consoleClientId") static Optional provideOptionalClientId(HttpServletRequest req) { return extractOptionalParameter(req, PARAM_CLIENT_ID); } @Provides - @Parameter(PARAM_CLIENT_ID) + @Parameter("consoleClientId") static String provideClientId(HttpServletRequest req) { return extractRequiredParameter(req, PARAM_CLIENT_ID); } @@ -76,7 +76,7 @@ public final class RegistrarConsoleModule { } @Provides - @Parameter("name") + @Parameter("consoleName") static Optional provideOptionalName(HttpServletRequest req) { return extractOptionalParameter(req, "name"); } @@ -178,7 +178,7 @@ public final class RegistrarConsoleModule { } @Provides - @Parameter("domain") + @Parameter("consoleDomain") static String provideDomain(HttpServletRequest req) { return extractRequiredParameter(req, "domain"); } diff --git a/core/src/main/java/google/registry/ui/server/registrar/RegistryLockGetAction.java b/core/src/main/java/google/registry/ui/server/registrar/RegistryLockGetAction.java index eb601e80d..08dc92332 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/RegistryLockGetAction.java +++ b/core/src/main/java/google/registry/ui/server/registrar/RegistryLockGetAction.java @@ -52,7 +52,7 @@ import javax.inject.Inject; import org.joda.time.DateTime; /** - * Servlet that allows for getting locks for a particular registrar. + * Action that allows for getting locks for a particular registrar. * *

Note: at the moment we have no mechanism for JSON GET/POSTs in the same class or at the same * URL, which is why this is distinct from the {@link RegistryLockPostAction}. @@ -90,7 +90,7 @@ public final class RegistryLockGetAction implements JsonGetAction { Response response, AuthenticatedRegistrarAccessor registrarAccessor, AuthResult authResult, - @Parameter(PARAM_CLIENT_ID) Optional paramClientId) { + @Parameter("consoleClientId") Optional paramClientId) { this.method = method; this.response = response; this.registrarAccessor = registrarAccessor; diff --git a/core/src/test/java/google/registry/request/RequestHandlerTest.java b/core/src/test/java/google/registry/request/RequestHandlerTest.java index e04ea9e74..835c7a871 100644 --- a/core/src/test/java/google/registry/request/RequestHandlerTest.java +++ b/core/src/test/java/google/registry/request/RequestHandlerTest.java @@ -199,7 +199,7 @@ public final class RequestHandlerTest { void beforeEach() throws Exception { // Initialize here, not inline, so that we pick up the mocked UserService. handler = - RequestHandler.createForTest( + RequestHandler.create( Component.class, () -> new Builder() { diff --git a/jetty/Dockerfile b/jetty/Dockerfile new file mode 100644 index 000000000..406fec7da --- /dev/null +++ b/jetty/Dockerfile @@ -0,0 +1,7 @@ +FROM jetty:12-jdk17 +ADD --chown=jetty:jetty build/jetty-base /jetty-base +ENV JETTY_BASE=/jetty-base +WORKDIR "$JETTY_BASE" +EXPOSE 8080 +ENTRYPOINT ["java", "-jar", "/usr/local/jetty/start.jar"] + diff --git a/jetty/build.gradle b/jetty/build.gradle new file mode 100644 index 000000000..3f95f79d8 --- /dev/null +++ b/jetty/build.gradle @@ -0,0 +1,52 @@ +// Copyright 2024 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. + +apply plugin: 'war' + +tasks.register('copyJettyBase', Copy) { + from(layout.projectDirectory.dir('src/main')) { + include 'jetty-base/**' + } + into layout.buildDirectory +} + +war { + setArchiveBaseName("root") + setDestinationDirectory(layout.buildDirectory.dir('jetty-base/webapps')) + dependsOn(tasks.named('copyJettyBase')) +} + +dependencies { + implementation project(':core') +} + +tasks.register('copyConsole', Copy) { + from("${rootDir}/console-webapp/dist/console-webapp") { + include "**/*" + } + into layout.buildDirectory.dir('jetty-base/webapps/console') + dependsOn(':console-webapp:buildConsoleWebappProd') +} + +tasks.register('stage') { + dependsOn(tasks.named('war')) + dependsOn(tasks.named('copyConsole')) +} + +tasks.register('buildNomulusImage', Exec) { + commandLine 'docker', 'build', '-t', 'nomulus', '.' + dependsOn(tasks.named('stage')) +} + +project.build.dependsOn(tasks.named('buildNomulusImage')) diff --git a/jetty/src/main/jetty-base/resources/jetty-logging.properties b/jetty/src/main/jetty-base/resources/jetty-logging.properties new file mode 100644 index 000000000..fba91898d --- /dev/null +++ b/jetty/src/main/jetty-base/resources/jetty-logging.properties @@ -0,0 +1,10 @@ +## Set logging levels from: ALL, TRACE, DEBUG, INFO, WARN, ERROR, OFF +org.eclipse.jetty.LEVEL=INFO +## Configure a level for an arbitrary logger tree +#com.example.LEVEL=INFO +## Configure a level for specific logger +#com.example.MyComponent.LEVEL=INFO +## Configure JMX Context Name +# org.eclipse.jetty.logging.jmx.context=JettyServer +## Hide stacks traces in an arbitrary logger tree +#com.example.STACKS=false diff --git a/jetty/src/main/jetty-base/start.d/ee8-deploy.ini b/jetty/src/main/jetty-base/start.d/ee8-deploy.ini new file mode 100644 index 000000000..69fdbdded --- /dev/null +++ b/jetty/src/main/jetty-base/start.d/ee8-deploy.ini @@ -0,0 +1,36 @@ +# --------------------------------------- +# Module: ee8-deploy +# This module enables webapp deployment from the `$JETTY_BASE/webapps` directory. +# --------------------------------------- +--modules=ee8-deploy + +## Monitored directory name (relative to $jetty.base) +# jetty.deploy.monitoredDir=webapps + +## Defaults Descriptor for all deployed webapps +# jetty.deploy.defaultsDescriptorPath=${jetty.base}/etc/webdefault-ee8.xml + +## Monitored directory scan period (seconds) +jetty.deploy.scanInterval=1 + +## Whether to extract *.war files +# jetty.deploy.extractWars=true + +## Whether to give the parent classloader priority +# jetty.deploy.parentLoaderPriority=true + +## Comma separated list of configuration classes to set. +# jetty.deploy.configurationClasses= + +## Pattern to select jars from the container classloader to be scanned (or null to scan no jars) +# jetty.deploy.containerScanJarPattern=.*/jetty-servlet-api-[^/]*\.jar$|.*/javax.servlet.jsp.jstl-.*\.jar$ + +## Pattern to select jars from the container classloader to be scanned (or null to scan all jars). +# jetty.deploy.webInfScanJarPattern= + +## Pattern to exclude discovered ServletContainerInitializers +# jetty.deploy.servletContainerInitializerExclusionPattern= + +## Order of discovered ServletContainerInitializers +# jetty.deploy.servletContainerInitializerOrder= + diff --git a/jetty/src/main/jetty-base/start.d/http.ini b/jetty/src/main/jetty-base/start.d/http.ini new file mode 100644 index 000000000..0617cabf4 --- /dev/null +++ b/jetty/src/main/jetty-base/start.d/http.ini @@ -0,0 +1,47 @@ +# --------------------------------------- +# Module: http +# Enables a clear-text HTTP connector. +# By default clear-text HTTP/1.1 is enabled, and clear-text HTTP/2 may be added by enabling the "http2c" module. +# --------------------------------------- +--modules=http + +### Clear-Text HTTP Connector Configuration + +## The host/address to bind the connector to. +jetty.http.host=0.0.0.0 + +## The port the connector listens on. +# jetty.http.port=8080 + +## The connector idle timeout, in milliseconds. +# jetty.http.idleTimeout=30000 + +## The number of acceptors (-1 picks a default value based on number of cores). +# jetty.http.acceptors=1 + +## The number of selectors (-1 picks a default value based on number of cores). +# jetty.http.selectors=-1 + +## The ServerSocketChannel accept queue backlog (0 picks the platform default). +# jetty.http.acceptQueueSize=0 + +## The thread priority delta to give to acceptor threads. +# jetty.http.acceptorPriorityDelta=0 + +## Whether to enable the SO_REUSEADDR socket option. +# jetty.http.reuseAddress=true + +## Whether to enable the SO_REUSEPORT socket option. +# jetty.http.reusePort=false + +## Whether to enable the TCP_NODELAY socket option on accepted sockets. +# jetty.http.acceptedTcpNoDelay=true + +## The SO_RCVBUF socket option to set on accepted sockets. +## A value of -1 indicates that the platform default is used. +# jetty.http.acceptedReceiveBufferSize=-1 + +## The SO_SNDBUF socket option to set on accepted sockets. +## A value of -1 indicates that the platform default is used. +# jetty.http.acceptedSendBufferSize=-1 + diff --git a/jetty/src/main/jetty-base/start.d/server.ini b/jetty/src/main/jetty-base/start.d/server.ini new file mode 100644 index 000000000..aa575c31b --- /dev/null +++ b/jetty/src/main/jetty-base/start.d/server.ini @@ -0,0 +1,100 @@ +# --------------------------------------- +# Module: server +# Enables and configures the Jetty server. +# This module does not enable any network protocol support. +# To enable a specific network protocol such as HTTP/1.1, you must enable the correspondent Jetty module. +# --------------------------------------- +--modules=server + +### Common HTTP configuration +## Scheme to use to build URIs for secure redirects +# jetty.httpConfig.secureScheme=https + +## Port to use to build URIs for secure redirects +# jetty.httpConfig.securePort=8443 + +## Response content buffer size (in bytes) +# jetty.httpConfig.outputBufferSize=32768 + +## Max response content write length that is buffered (in bytes) +# jetty.httpConfig.outputAggregationSize=8192 + +## If HTTP/1.x persistent connections should be enabled +# jetty.httpConfig.persistentConnectionsEnabled=true + +## Max request headers size (in bytes) +# jetty.httpConfig.requestHeaderSize=8192 + +## Max response headers size (in bytes) +# jetty.httpConfig.responseHeaderSize=8192 + +## Whether to send the Server: header +# jetty.httpConfig.sendServerVersion=true + +## Whether to send the Date: header +# jetty.httpConfig.sendDateHeader=false + +## Max per-connection header cache size (in nodes) +# jetty.httpConfig.headerCacheSize=1024 + +## Whether, for requests with content, delay dispatch until some content has arrived +# jetty.httpConfig.delayDispatchUntilContent=true + +## Maximum number of error dispatches to prevent looping +# jetty.httpConfig.maxErrorDispatches=10 + +## Relative Redirect Locations allowed +# jetty.httpConfig.relativeRedirectAllowed=true + +## Whether to use direct ByteBuffers for reading or writing +# jetty.httpConfig.useInputDirectByteBuffers=true +# jetty.httpConfig.useOutputDirectByteBuffers=true + +## HTTP Compliance: RFC7230, RFC7230_LEGACY, RFC2616, RFC2616_LEGACY, LEGACY +# jetty.httpConfig.compliance=RFC7230 + +## URI Compliance: DEFAULT, LEGACY, RFC3986, RFC3986_UNAMBIGUOUS, UNSAFE +# jetty.httpConfig.uriCompliance=DEFAULT + +## Cookie compliance mode for parsing request Cookie headers: RFC6265_STRICT, RFC6265, RFC6265_LEGACY, RFC2965, RFC2965_LEGACY +# jetty.httpConfig.requestCookieCompliance=RFC6265 + +## Cookie compliance mode for generating response Set-Cookie: RFC2965, RFC6265 +# jetty.httpConfig.responseCookieCompliance=RFC6265 + +### Server configuration +## Whether ctrl+c on the console gracefully stops the Jetty server +# jetty.server.stopAtShutdown=true + +## Timeout in ms to apply when stopping the server gracefully +# jetty.server.stopTimeout=5000 + +## Dump the state of the Jetty server, components, and webapps after startup +# jetty.server.dumpAfterStart=false + +## The temporary directory used by the Jetty server and as a root for its contexts +# jetty.server.tempDirectory= + +## Dump the state of the Jetty server, components, and webapps before shutdown +# jetty.server.dumpBeforeStop=false + +### Server Scheduler Configuration +## The scheduler thread name, defaults to "Scheduler-{hashCode()}" if blank. +# jetty.scheduler.name= + +## Whether the server scheduler threads are daemon. +# jetty.scheduler.daemon=false + +## The number of server scheduler threads. +# jetty.scheduler.threads=1 + +## Whether the handlers of the ContextHandlerCollection can be updated once the server is started +## If set to false, then eeN-deploy module jetty.deploy.scanInterval should also be set to 0. +# jetty.server.contexts.dynamic=true + +## Should the DefaultHandler serve the jetty favicon.ico from the root. +# jetty.server.default.serveFavIcon=true + +## Should the DefaultHandler show a list of known contexts in a root 404 response. +# jetty.server.default.showContexts=true + diff --git a/jetty/src/main/webapp/WEB-INF/web.xml b/jetty/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..45c483687 --- /dev/null +++ b/jetty/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,20 @@ + + + + + + + registry + google.registry.module.RegistryServlet + 1 + + + + + registry + /* + + diff --git a/settings.gradle b/settings.gradle index f0f0b72f7..0df4715e3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -45,4 +45,5 @@ include 'services:backend' include 'services:bsa' include 'services:tools' include 'services:pubapi' -include "console-webapp" +include 'console-webapp' +include 'jetty'