mirror of
https://github.com/google/nomulus
synced 2026-09-19 06:32:00 +00:00
Add Java code for storing and using IDN tables per-TLD (#1977)
This includes changes to make sure that we use the proper per-TLD IDN tables as well as setting/updating/removing them via the Create/Update TLD commands.
This commit is contained in:
@@ -176,8 +176,7 @@ public class DomainFlowUtils {
|
||||
CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('0', '9').or(CharMatcher.anyOf("-.")));
|
||||
|
||||
/** Default validator used to determine if an IDN name can be provisioned on a TLD. */
|
||||
private static final IdnLabelValidator IDN_LABEL_VALIDATOR =
|
||||
IdnLabelValidator.createDefaultIdnLabelValidator();
|
||||
private static final IdnLabelValidator IDN_LABEL_VALIDATOR = new IdnLabelValidator();
|
||||
|
||||
/** The maximum number of DS records allowed on a domain. */
|
||||
private static final int MAX_DS_RECORDS_PER_DOMAIN = 8;
|
||||
|
||||
@@ -52,6 +52,7 @@ import google.registry.model.tld.label.PremiumList;
|
||||
import google.registry.model.tld.label.ReservedList;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.converter.JodaMoneyType;
|
||||
import google.registry.tldconfig.idn.IdnTableEnum;
|
||||
import google.registry.util.Idn;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -487,6 +488,9 @@ public class Registry extends ImmutableObject implements Buildable, UnsafeSerial
|
||||
*/
|
||||
List<VKey<AllocationToken>> defaultPromoTokens;
|
||||
|
||||
/** A set of allowed {@link IdnTableEnum}s for this TLD, or empty if we should use the default. */
|
||||
Set<IdnTableEnum> idnTables;
|
||||
|
||||
public String getTldStr() {
|
||||
return tldStr;
|
||||
}
|
||||
@@ -694,6 +698,10 @@ public class Registry extends ImmutableObject implements Buildable, UnsafeSerial
|
||||
return nullToEmptyImmutableCopy(defaultPromoTokens);
|
||||
}
|
||||
|
||||
public ImmutableSet<IdnTableEnum> getIdnTables() {
|
||||
return nullToEmptyImmutableCopy(idnTables);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
return new Builder(clone(this));
|
||||
@@ -992,6 +1000,11 @@ public class Registry extends ImmutableObject implements Buildable, UnsafeSerial
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setIdnTables(ImmutableSet<IdnTableEnum> idnTables) {
|
||||
getInstance().idnTables = idnTables;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Registry build() {
|
||||
final Registry instance = getInstance();
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// Copyright 2023 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.persistence.converter;
|
||||
|
||||
import google.registry.tldconfig.idn.IdnTableEnum;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Converter;
|
||||
|
||||
/** JPA {@link AttributeConverter} for storing/retrieving {@link IdnTableEnum}s. */
|
||||
@Converter(autoApply = true)
|
||||
public class IdnTableEnumSetConverter extends StringSetConverterBase<IdnTableEnum> {
|
||||
|
||||
@Override
|
||||
String toString(IdnTableEnum element) {
|
||||
return element.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
IdnTableEnum fromString(String value) {
|
||||
return IdnTableEnum.valueOf(value);
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@ package google.registry.tldconfig.idn;
|
||||
import static google.registry.tldconfig.idn.IdnTableEnum.EXTENDED_LATIN;
|
||||
import static google.registry.tldconfig.idn.IdnTableEnum.JA;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.util.Idn;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -26,23 +26,8 @@ import java.util.Optional;
|
||||
public final class IdnLabelValidator {
|
||||
|
||||
/** Most TLDs will use this generic list of IDN tables. */
|
||||
private static final ImmutableList<IdnTableEnum> DEFAULT_IDN_TABLES =
|
||||
ImmutableList.of(EXTENDED_LATIN, JA);
|
||||
|
||||
private static final ImmutableMap<String, ImmutableList<IdnTableEnum>>
|
||||
DEFAULT_IDN_TABLE_LISTS_PER_TLD =
|
||||
ImmutableMap.of("xn--q9jyb4c", ImmutableList.of(EXTENDED_LATIN, JA));
|
||||
|
||||
/** Some TLDs have their own IDN tables, configured here. */
|
||||
private ImmutableMap<String, ImmutableList<IdnTableEnum>> idnTableListsPerTld;
|
||||
|
||||
IdnLabelValidator(ImmutableMap<String, ImmutableList<IdnTableEnum>> indTableListsPerTld) {
|
||||
this.idnTableListsPerTld = indTableListsPerTld;
|
||||
}
|
||||
|
||||
public static IdnLabelValidator createDefaultIdnLabelValidator() {
|
||||
return new IdnLabelValidator(DEFAULT_IDN_TABLE_LISTS_PER_TLD);
|
||||
}
|
||||
private static final ImmutableSet<IdnTableEnum> DEFAULT_IDN_TABLES =
|
||||
ImmutableSet.of(EXTENDED_LATIN, JA);
|
||||
|
||||
/**
|
||||
* Returns name of first matching {@link IdnTable} if domain label is valid for the given TLD.
|
||||
@@ -50,10 +35,13 @@ public final class IdnLabelValidator {
|
||||
* <p>A label is valid if it is considered valid by at least one configured IDN table for that
|
||||
* TLD. If no match is found, an absent value is returned.
|
||||
*/
|
||||
public Optional<String> findValidIdnTableForTld(String label, String tld) {
|
||||
public Optional<String> findValidIdnTableForTld(String label, String tldStr) {
|
||||
String unicodeString = Idn.toUnicode(label);
|
||||
for (IdnTableEnum idnTable :
|
||||
Optional.ofNullable(idnTableListsPerTld.get(tld)).orElse(DEFAULT_IDN_TABLES)) {
|
||||
Registry tld = Registry.get(tldStr); // uses the cache
|
||||
ImmutableSet<IdnTableEnum> idnTablesForTld = tld.getIdnTables();
|
||||
ImmutableSet<IdnTableEnum> idnTables =
|
||||
idnTablesForTld.isEmpty() ? DEFAULT_IDN_TABLES : idnTablesForTld;
|
||||
for (IdnTableEnum idnTable : idnTables) {
|
||||
if (idnTable.getTable().isValidLabel(unicodeString)) {
|
||||
return Optional.of(idnTable.getTable().getName());
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.tools.UpdateOrDeleteAllocationTokensCommand.getTokenKeys;
|
||||
import static google.registry.util.CollectionUtils.findDuplicates;
|
||||
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||
@@ -34,9 +35,11 @@ import google.registry.model.tld.Registry.TldState;
|
||||
import google.registry.model.tld.Registry.TldType;
|
||||
import google.registry.model.tld.label.PremiumList;
|
||||
import google.registry.model.tld.label.PremiumListDao;
|
||||
import google.registry.tldconfig.idn.IdnTableEnum;
|
||||
import google.registry.tools.params.OptionalStringParameter;
|
||||
import google.registry.tools.params.TransitionListParameter.BillingCostTransitions;
|
||||
import google.registry.tools.params.TransitionListParameter.TldStateTransitions;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -244,6 +247,15 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
|
||||
+ " present default tokens.")
|
||||
List<String> defaultTokens;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
names = "--idn_tables",
|
||||
description =
|
||||
"A comma-separated list of the IDN tables to use for this TLD. Specify an empty list to"
|
||||
+ " remove any previously-set tables and to use the default. All elements must be"
|
||||
+ " IdnTableEnum values")
|
||||
List<String> idnTables;
|
||||
|
||||
/** Returns the existing registry (for update) or null (for creates). */
|
||||
@Nullable
|
||||
abstract Registry getOldRegistry(String tld);
|
||||
@@ -392,6 +404,23 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
|
||||
builder.setDefaultPromoTokens(getTokenKeys(defaultTokens, null));
|
||||
}
|
||||
}
|
||||
if (idnTables != null) {
|
||||
if (idnTables.equals(ImmutableList.of(""))) {
|
||||
builder.setIdnTables(ImmutableSet.of());
|
||||
} else {
|
||||
ImmutableSet<String> upperCaseIdnTables =
|
||||
idnTables.stream().map(String::toUpperCase).collect(toImmutableSet());
|
||||
ImmutableSet<String> validIdnStringValues =
|
||||
Arrays.stream(IdnTableEnum.values()).map(Enum::name).collect(toImmutableSet());
|
||||
checkArgument(
|
||||
validIdnStringValues.containsAll(upperCaseIdnTables),
|
||||
"IDN tables %s contained invalid value(s). Possible values: %s",
|
||||
upperCaseIdnTables,
|
||||
validIdnStringValues);
|
||||
builder.setIdnTables(
|
||||
upperCaseIdnTables.stream().map(IdnTableEnum::valueOf).collect(toImmutableSet()));
|
||||
}
|
||||
}
|
||||
// Update the Registry object.
|
||||
setCommandSpecificProperties(builder);
|
||||
stageEntityChange(oldRegistry, builder.build());
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
<class>google.registry.persistence.converter.DatabaseMigrationScheduleTransitionConverter</class>
|
||||
<class>google.registry.persistence.converter.DateTimeConverter</class>
|
||||
<class>google.registry.persistence.converter.DurationConverter</class>
|
||||
<class>google.registry.persistence.converter.IdnTableEnumSetConverter</class>
|
||||
<class>google.registry.persistence.converter.InetAddressSetConverter</class>
|
||||
<class>google.registry.persistence.converter.LocalDateConverter</class>
|
||||
<class>google.registry.persistence.converter.PostalInfoChoiceListConverter</class>
|
||||
|
||||
Reference in New Issue
Block a user