google-nomulus/java/google/registry/flows/domain/DomainApplicationCreateFlow.java
ctingue 273fc0014d Add EAP fees to domain create flow
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=126411200
2016-07-01 13:42:58 -04:00

258 lines
12 KiB
Java

// Copyright 2016 The Domain Registry 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.domain;
import static google.registry.flows.domain.DomainFlowUtils.DISALLOWED_TLD_STATES_FOR_LAUNCH_FLOWS;
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
import static google.registry.model.eppoutput.Result.Code.Success;
import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName;
import static google.registry.model.index.ForeignKeyIndex.loadAndGetReference;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import google.registry.flows.EppException;
import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.ObjectAlreadyExistsException;
import google.registry.flows.EppException.RequiredParameterMissingException;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainApplication.Builder;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.FeeCreateExtension;
import google.registry.model.domain.fee.FeeCreateResponseExtension;
import google.registry.model.domain.launch.ApplicationStatus;
import google.registry.model.domain.launch.LaunchCreateExtension;
import google.registry.model.domain.launch.LaunchCreateResponseExtension;
import google.registry.model.domain.launch.LaunchPhase;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppoutput.CreateData.DomainCreateData;
import google.registry.model.eppoutput.EppOutput;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import google.registry.model.registry.Registry.TldState;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.smd.AbstractSignedMark;
import google.registry.model.smd.EncodedSignedMark;
import java.util.List;
import javax.inject.Inject;
/**
* An EPP flow that creates a new application for a domain resource.
*
* @error {@link google.registry.flows.EppException.UnimplementedExtensionException}
* @error {@link google.registry.flows.ResourceFlow.BadCommandForRegistryPhaseException}
* @error {@link google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException}
* @error {@link google.registry.flows.ResourceCreateFlow.ResourceAlreadyExistsException}
* @error {@link BaseDomainCreateFlow.AcceptedTooLongAgoException}
* @error {@link BaseDomainCreateFlow.ClaimsPeriodEndedException}
* @error {@link BaseDomainCreateFlow.ExpiredClaimException}
* @error {@link BaseDomainCreateFlow.InvalidTcnIdChecksumException}
* @error {@link BaseDomainCreateFlow.InvalidTrademarkValidatorException}
* @error {@link BaseDomainCreateFlow.MalformedTcnIdException}
* @error {@link BaseDomainCreateFlow.MaxSigLifeNotSupportedException}
* @error {@link BaseDomainCreateFlow.MissingClaimsNoticeException}
* @error {@link BaseDomainCreateFlow.UnexpectedClaimsNoticeException}
* @error {@link BaseDomainCreateFlow.UnsupportedMarkTypeException}
* @error {@link DomainApplicationCreateFlow.LandrushApplicationDisallowedDuringSunriseException}
* @error {@link DomainApplicationCreateFlow.NoticeCannotBeUsedWithSignedMarkException}
* @error {@link DomainApplicationCreateFlow.SunriseApplicationDisallowedDuringLandrushException}
* @error {@link DomainApplicationCreateFlow.UncontestedSunriseApplicationBlockedInLandrushException}
* @error {@link DomainFlowUtils.BadDomainNameCharacterException}
* @error {@link DomainFlowUtils.BadDomainNamePartsCountException}
* @error {@link DomainFlowUtils.BadPeriodUnitException}
* @error {@link DomainFlowUtils.Base64RequiredForEncodedSignedMarksException}
* @error {@link DomainFlowUtils.CurrencyUnitMismatchException}
* @error {@link DomainFlowUtils.CurrencyValueScaleException}
* @error {@link DomainFlowUtils.DashesInThirdAndFourthException}
* @error {@link DomainFlowUtils.DomainLabelTooLongException}
* @error {@link DomainFlowUtils.DomainReservedException}
* @error {@link DomainFlowUtils.DuplicateContactForRoleException}
* @error {@link DomainFlowUtils.EmptyDomainNamePartException}
* @error {@link DomainFlowUtils.FeesMismatchException}
* @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException}
* @error {@link DomainFlowUtils.InvalidIdnDomainLabelException}
* @error {@link DomainFlowUtils.InvalidPunycodeException}
* @error {@link DomainFlowUtils.LaunchPhaseMismatchException}
* @error {@link DomainFlowUtils.LeadingDashException}
* @error {@link DomainFlowUtils.LinkedResourcesDoNotExistException}
* @error {@link DomainFlowUtils.MissingContactTypeException}
* @error {@link DomainFlowUtils.NameserversNotAllowedException}
* @error {@link DomainFlowUtils.NoMarksFoundMatchingDomainException}
* @error {@link DomainFlowUtils.PremiumNameBlockedException}
* @error {@link DomainFlowUtils.RegistrantNotAllowedException}
* @error {@link DomainFlowUtils.SignedMarksMustBeEncodedException}
* @error {@link DomainFlowUtils.SignedMarkCertificateExpiredException}
* @error {@link DomainFlowUtils.SignedMarkCertificateInvalidException}
* @error {@link DomainFlowUtils.SignedMarkCertificateNotYetValidException}
* @error {@link DomainFlowUtils.SignedMarkCertificateRevokedException}
* @error {@link DomainFlowUtils.SignedMarkCertificateSignatureException}
* @error {@link DomainFlowUtils.SignedMarkEncodingErrorException}
* @error {@link DomainFlowUtils.SignedMarkParsingErrorException}
* @error {@link DomainFlowUtils.SignedMarkRevokedErrorException}
* @error {@link DomainFlowUtils.SignedMarkSignatureException}
* @error {@link DomainFlowUtils.TldDoesNotExistException}
* @error {@link DomainFlowUtils.TooManyDsRecordsException}
* @error {@link DomainFlowUtils.TooManyNameserversException}
* @error {@link DomainFlowUtils.TooManySignedMarksException}
* @error {@link DomainFlowUtils.TrailingDashException}
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
*/
public class DomainApplicationCreateFlow extends BaseDomainCreateFlow<DomainApplication, Builder> {
@Inject DomainApplicationCreateFlow() {}
@Override
protected void initDomainCreateFlow() {
registerExtensions(FeeCreateExtension.class, LaunchCreateExtension.class);
}
@Override
protected void validateDomainLaunchCreateExtension() throws EppException {
if (launchCreate.getSignedMarks().isEmpty()) {
// During sunrise, a signed mark is required since only trademark holders are allowed to
// create an application. However, we found no marks (ie, this was a landrush application).
if (tldState == TldState.SUNRISE) {
throw new LandrushApplicationDisallowedDuringSunriseException();
}
} else {
if (launchCreate.getNotice() != null) { // Can't use a claims notice id with a signed mark.
throw new NoticeCannotBeUsedWithSignedMarkException();
}
if (tldState == TldState.LANDRUSH) {
throw new SunriseApplicationDisallowedDuringLandrushException();
}
}
}
@Override
protected void verifyDomainCreateIsAllowed() throws EppException {
validateFeeChallenge(
targetId, getTld(), now, feeCreate, commandOperations.getTotalCost());
if (tldState == TldState.LANDRUSH && !isSuperuser) {
// Prohibit creating a landrush application in LANDRUSH (but not in SUNRUSH) if there is
// exactly one sunrise application for the same name.
List<DomainApplication> applications = FluentIterable
.from(loadActiveApplicationsByDomainName(targetId, now))
.limit(2)
.toList();
if (applications.size() == 1 && applications.get(0).getPhase().equals(LaunchPhase.SUNRISE)) {
throw new UncontestedSunriseApplicationBlockedInLandrushException();
}
}
// Fail if the domain is already registered (e.g. this is a landrush application but the domain
// was awarded at the end of sunrise).
if (loadAndGetReference(DomainResource.class, targetId, now) != null) {
throw new ResourceAlreadyExistsException(targetId);
}
}
@Override
protected void setDomainCreateProperties(Builder builder) {
builder
.setCreationTrid(trid)
.setPhase(launchCreate.getPhase())
.setApplicationStatus(ApplicationStatus.VALIDATED)
.addStatusValue(StatusValue.PENDING_CREATE);
if (!launchCreate.getSignedMarks().isEmpty()) {
builder.setEncodedSignedMarks(FluentIterable
.from(launchCreate.getSignedMarks())
.transform(new Function<AbstractSignedMark, EncodedSignedMark>() {
@Override
public EncodedSignedMark apply(AbstractSignedMark abstractSignedMark) {
// We verified that this is the case in verifyDomainCreateIsAllowed().
return (EncodedSignedMark) abstractSignedMark;
}})
.toList());
}
}
@Override
protected final ImmutableSet<TldState> getDisallowedTldStates() {
return DISALLOWED_TLD_STATES_FOR_LAUNCH_FLOWS;
}
@Override
protected final HistoryEntry.Type getHistoryEntryType() {
return HistoryEntry.Type.DOMAIN_APPLICATION_CREATE;
}
@Override
protected final Period getCommandPeriod() {
return command.getPeriod();
}
@Override
protected boolean tryToLoadExisting() {
// Multiple domain applications can be created for the same targetId (which is the fully
// qualified domain name), so don't try to load an existing resource with the same target id.
return false;
}
@Override
protected final EppOutput getOutput() {
ImmutableList.Builder<ResponseExtension> responseExtensionsBuilder =
new ImmutableList.Builder<>();
responseExtensionsBuilder.add(new LaunchCreateResponseExtension.Builder()
.setPhase(launchCreate.getPhase())
.setApplicationId(newResource.getForeignKey())
.build());
if (feeCreate != null) {
responseExtensionsBuilder.add(new FeeCreateResponseExtension.Builder()
.setCurrency(commandOperations.getCurrency())
.setFee(commandOperations.getFees())
.build());
}
return createOutput(
Success,
DomainCreateData.create(newResource.getFullyQualifiedDomainName(), now, null),
responseExtensionsBuilder.build());
}
/** Landrush applications are disallowed during sunrise. */
static class LandrushApplicationDisallowedDuringSunriseException
extends RequiredParameterMissingException {
public LandrushApplicationDisallowedDuringSunriseException() {
super("Landrush applications are disallowed during sunrise");
}
}
/** A notice cannot be specified when using a signed mark. */
static class NoticeCannotBeUsedWithSignedMarkException extends CommandUseErrorException {
public NoticeCannotBeUsedWithSignedMarkException() {
super("A notice cannot be specified when using a signed mark");
}
}
/** Sunrise applications are disallowed during landrush. */
static class SunriseApplicationDisallowedDuringLandrushException
extends CommandUseErrorException {
public SunriseApplicationDisallowedDuringLandrushException() {
super("Sunrise applications are disallowed during landrush");
}
}
/** This name has already been claimed by a sunrise applicant. */
static class UncontestedSunriseApplicationBlockedInLandrushException
extends ObjectAlreadyExistsException {
public UncontestedSunriseApplicationBlockedInLandrushException() {
super("This name has already been claimed by a sunrise applicant");
}
}
}