mirror of
https://github.com/google/nomulus
synced 2026-08-09 16:56:11 +00:00
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0345ddf89 | ||
|
|
e9f20b3401 | ||
|
|
64e7a593ef | ||
|
|
135ab66e55 | ||
|
|
69acb9f6de | ||
|
|
5359f4640a | ||
|
|
5c2856e3e2 | ||
|
|
86e1fb85b6 | ||
|
|
301ab54fb4 | ||
|
|
2c6d71f04c | ||
|
|
ee4e6ace2a |
@@ -288,20 +288,6 @@ subprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (['util', 'proxy', 'core', 'prober', 'db'].contains(project.name)) return
|
||||
|
||||
// TODO(weiminyu): investigate if the block below is still needed
|
||||
ext.relativePath = "google/registry/${project.name}"
|
||||
|
||||
sourceSets.each {
|
||||
it.java {
|
||||
include "${project.relativePath}/"
|
||||
}
|
||||
it.resources {
|
||||
include "${project.relativePath}/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If "-P verboseTestOutput=true" is passed in, configure all subprojects to dump all of their
|
||||
|
||||
+47
-16
@@ -534,8 +534,8 @@ task compileProdJS(type: JavaExec) {
|
||||
|
||||
compileJava.dependsOn jaxbToJava
|
||||
compileJava.dependsOn soyToJava
|
||||
// The Closure JS compiler does not support Windows. It is fine to disable it if all we want to do
|
||||
// is to complile the Java code on Windows.
|
||||
// The Closure JS compiler does not support Windows. It is fine to disable it if
|
||||
// all we want to do is to complile the Java code on Windows.
|
||||
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||
compileJava.dependsOn compileProdJS
|
||||
assemble.dependsOn compileProdJS
|
||||
@@ -590,14 +590,43 @@ artifacts {
|
||||
*/
|
||||
class FilteringTest extends Test {
|
||||
|
||||
void setTests(List<String> tests) {
|
||||
// Common exclude pattern. See README in parent directory for explanation.
|
||||
exclude "**/*TestCase.*", "**/*TestSuite.*"
|
||||
include tests
|
||||
private void applyTestFilter() {
|
||||
if (project.testFilter) {
|
||||
testNameIncludePatterns = project.testFilter.split(',')
|
||||
|
||||
// By default, gradle test tasks will produce a failure if no tests
|
||||
// match the include/exclude/filter rules. Since test filtering allows us
|
||||
// to select a set of tests from a particular task, we don't want this
|
||||
// behavior.
|
||||
filter.failOnNoMatchingTests = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to false if you also want to include TestCase and TestSuite classes.
|
||||
*
|
||||
* <p>Must be defined before "test", if at all.
|
||||
*/
|
||||
boolean excludeTestCases = true
|
||||
|
||||
void setTests(List<String> tests) {
|
||||
// Common exclude pattern. See README in parent directory for explanation.
|
||||
if (excludeTestCases) {
|
||||
exclude "**/*TestCase.*", "**/*TestSuite.*"
|
||||
}
|
||||
include tests
|
||||
applyTestFilter()
|
||||
}
|
||||
|
||||
/**
|
||||
* Include all of the tests (except Test{Case,TestSuite}). This actually
|
||||
* doesn't explicitly "include" anything, in which cast the Test class tries
|
||||
* to include everything that is not explicitly excluded.
|
||||
*/
|
||||
void includeAllTests() {
|
||||
exclude "**/*TestCase.*", "**/*TestSuite.*"
|
||||
applyTestFilter()
|
||||
}
|
||||
}
|
||||
|
||||
task fragileTest(type: FilteringTest) {
|
||||
@@ -620,12 +649,9 @@ task outcastTest(type: FilteringTest) {
|
||||
}
|
||||
|
||||
// Dedicated test suite for schema-dependent tests.
|
||||
task sqlIntegrationTest(type: Test) {
|
||||
include 'google/registry/schema/integration/SqlIntegrationTestSuite.*'
|
||||
// Copied from FilteringTest. Not inheriting b/c it excludes TestSuites.
|
||||
if (project.testFilter) {
|
||||
testNameIncludePatterns = project.testFilter.split(',')
|
||||
}
|
||||
task sqlIntegrationTest(type: FilteringTest) {
|
||||
excludeTestCases = false
|
||||
tests = ['google/registry/schema/integration/SqlIntegrationTestSuite.*']
|
||||
}
|
||||
|
||||
task findGoldenImages(type: JavaExec) {
|
||||
@@ -710,9 +736,8 @@ task flowDocsTool(type: JavaExec) {
|
||||
args arguments
|
||||
}
|
||||
|
||||
test {
|
||||
// Common exclude pattern. See README in parent directory for explanation.
|
||||
exclude "**/*TestCase.*", "**/*TestSuite.*"
|
||||
task standardTest(type: FilteringTest) {
|
||||
includeAllTests()
|
||||
exclude fragileTestPatterns
|
||||
exclude outcastTestPatterns
|
||||
|
||||
@@ -734,7 +759,13 @@ test {
|
||||
doFirst {
|
||||
new File(screenshotsDir).deleteDir()
|
||||
}
|
||||
}.dependsOn(fragileTest, outcastTest)
|
||||
}
|
||||
|
||||
test {
|
||||
// Don't run any tests from this task, all testing gets done in the
|
||||
// FilteringTest tasks.
|
||||
exclude "**"
|
||||
}.dependsOn(fragileTest, outcastTest, standardTest)
|
||||
|
||||
createUberJar('nomulus', 'nomulus', 'google.registry.tools.RegistryTool')
|
||||
project.nomulus.dependsOn project(':third_party').jar
|
||||
|
||||
@@ -204,7 +204,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -202,7 +202,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -204,7 +204,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -228,7 +228,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -226,7 +226,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -240,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -240,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -42,10 +42,6 @@ module.exports = function(config) {
|
||||
pattern: 'core/build/generated/source/custom/main/**/*.soy.js',
|
||||
included: false
|
||||
},
|
||||
{
|
||||
pattern: 'node_modules/soyutils_usegoog.js',
|
||||
included: false
|
||||
},
|
||||
{
|
||||
pattern: 'node_modules/google-closure-library/closure/goog/deps.js',
|
||||
included: false,
|
||||
@@ -70,7 +66,6 @@ module.exports = function(config) {
|
||||
'node_modules/google-closure-library/closure/**/*.js': ['closure'],
|
||||
'core/src/*/javascript/**/*.js': ['closure'],
|
||||
'core/build/generated/source/custom/main/**/*.soy.js': ['closure'],
|
||||
'node_modules/soyutils_usegoog.js': ['closure']
|
||||
},
|
||||
proxies: {
|
||||
"/assets/": "/base/core/build/resources/main/google/registry/ui/assets/"
|
||||
|
||||
@@ -1296,12 +1296,6 @@ public final class RegistryConfig {
|
||||
return config.registryTool.clientSecret;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("toolsCloudSqlJdbcUrl")
|
||||
public static String providesToolsCloudSqlJdbcUrl(RegistryConfigSettings config) {
|
||||
return config.registryTool.jdbcUrl;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("toolsCloudSqlUsername")
|
||||
public static String providesToolsCloudSqlUsername(RegistryConfigSettings config) {
|
||||
|
||||
@@ -213,7 +213,6 @@ public class RegistryConfigSettings {
|
||||
public static class RegistryTool {
|
||||
public String clientId;
|
||||
public String clientSecret;
|
||||
public String jdbcUrl;
|
||||
public String username;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,6 +422,4 @@ registryTool:
|
||||
clientId: YOUR_CLIENT_ID
|
||||
# OAuth client secret used by the tool.
|
||||
clientSecret: YOUR_CLIENT_SECRET
|
||||
# Nomulus tool uses a different jdbc url and user to connect to Cloud SQL
|
||||
jdbcUrl: jdbc:postgresql://localhost/tool
|
||||
username: toolusername
|
||||
|
||||
@@ -55,6 +55,12 @@
|
||||
<url-pattern>/registrar-settings</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Registry lock get/post/verify. -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>frontend-servlet</servlet-name>
|
||||
<url-pattern>/registry-lock-get</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Security config -->
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
|
||||
@@ -187,6 +187,7 @@ import org.joda.time.Duration;
|
||||
* @error {@link DomainFlowUtils.UnexpectedClaimsNoticeException}
|
||||
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
|
||||
* @error {@link DomainFlowUtils.UnsupportedMarkTypeException}
|
||||
* @error {@link DomainPricingLogic.AllocationTokenInvalidForPremiumNameException}
|
||||
*/
|
||||
@ReportingSpec(ActivityReportField.DOMAIN_CREATE)
|
||||
public class DomainCreateFlow implements TransactionalFlow {
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.pricing.PricingEngineProxy.getDomainFeeClass;
|
||||
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
||||
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.CommandUseErrorException;
|
||||
import google.registry.flows.FlowScope;
|
||||
import google.registry.flows.custom.DomainPricingCustomLogic;
|
||||
import google.registry.flows.custom.DomainPricingCustomLogic.CreatePriceParameters;
|
||||
@@ -182,13 +182,14 @@ public final class DomainPricingLogic {
|
||||
}
|
||||
|
||||
private Money getDomainCreateCostWithDiscount(
|
||||
String domainName, DateTime date, int years, Optional<AllocationToken> allocationToken) {
|
||||
String domainName, DateTime date, int years, Optional<AllocationToken> allocationToken)
|
||||
throws EppException {
|
||||
DomainPrices domainPrices = PricingEngineProxy.getPricesForDomainName(domainName, date);
|
||||
checkArgument(
|
||||
!allocationToken.isPresent()
|
||||
|| allocationToken.get().getDiscountFraction() == 0.0
|
||||
|| !domainPrices.isPremium(),
|
||||
"A nonzero discount code cannot be applied to premium domains");
|
||||
if (allocationToken.isPresent()
|
||||
&& allocationToken.get().getDiscountFraction() != 0.0
|
||||
&& domainPrices.isPremium()) {
|
||||
throw new AllocationTokenInvalidForPremiumNameException();
|
||||
}
|
||||
Money oneYearCreateCost = domainPrices.getCreateCost();
|
||||
Money totalDomainCreateCost = oneYearCreateCost.multipliedBy(years);
|
||||
// If a discount is applicable, apply it only to the first year
|
||||
@@ -200,4 +201,12 @@ public final class DomainPricingLogic {
|
||||
}
|
||||
return totalDomainCreateCost;
|
||||
}
|
||||
|
||||
/** An allocation token was provided that is invalid for premium domains. */
|
||||
public static class AllocationTokenInvalidForPremiumNameException
|
||||
extends CommandUseErrorException {
|
||||
public AllocationTokenInvalidForPremiumNameException() {
|
||||
super("A nonzero discount code cannot be applied to premium domains");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,16 @@ public class Cursor extends ImmutableObject {
|
||||
* stored is the last time that registrar changes were successfully synced to the sheet. If
|
||||
* there were no changes since the last time the action run, the cursor is not updated.
|
||||
*/
|
||||
SYNC_REGISTRAR_SHEET(EntityGroupRoot.class);
|
||||
SYNC_REGISTRAR_SHEET(EntityGroupRoot.class),
|
||||
|
||||
/** Cursor for tracking monthly uploads of ICANN transaction reports. */
|
||||
ICANN_UPLOAD_TX(Registry.class),
|
||||
|
||||
/** Cursor for tracking monthly uploads of ICANN activity reports. */
|
||||
ICANN_UPLOAD_ACTIVITY(Registry.class),
|
||||
|
||||
/** Cursor for tracking monthly upload of MANIFEST.txt to ICANN. */
|
||||
ICANN_UPLOAD_MANIFEST(EntityGroupRoot.class);
|
||||
|
||||
/** See the definition of scope on {@link #getScopeClass}. */
|
||||
private final Class<? extends ImmutableObject> scope;
|
||||
|
||||
@@ -30,6 +30,7 @@ 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;
|
||||
|
||||
/** Dagger component with per-request lifetime for "default" App Engine module. */
|
||||
@RequestScope
|
||||
@@ -50,6 +51,8 @@ interface FrontendRequestComponent {
|
||||
OteStatusAction oteStatusAction();
|
||||
RegistrarSettingsAction registrarSettingsAction();
|
||||
|
||||
RegistryLockGetAction registryLockGetAction();
|
||||
|
||||
@Subcomponent.Builder
|
||||
abstract class Builder implements RequestComponentBuilder<FrontendRequestComponent> {
|
||||
@Override public abstract Builder requestModule(RequestModule requestModule);
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
// Copyright 2019 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;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Maps;
|
||||
import java.io.File;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Stream;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
|
||||
import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
import org.hibernate.tool.schema.TargetType;
|
||||
|
||||
/** Utility class to export DDL script for given {@link javax.persistence.Entity} classes. */
|
||||
public class HibernateSchemaExporter {
|
||||
private final String jdbcUrl;
|
||||
private final String username;
|
||||
private final String password;
|
||||
|
||||
private HibernateSchemaExporter(String jdbcUrl, String username, String password) {
|
||||
this.jdbcUrl = jdbcUrl;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/** Constructs a {@link HibernateSchemaExporter} instance. */
|
||||
public static HibernateSchemaExporter create(String jdbcUrl, String username, String password) {
|
||||
return new HibernateSchemaExporter(jdbcUrl, username, password);
|
||||
}
|
||||
|
||||
/** Exports DDL script to the {@code outputFile} for the given {@code entityClasses}. */
|
||||
public void export(ImmutableList<Class> entityClasses, File outputFile) {
|
||||
// Configure Hibernate settings.
|
||||
Map<String, String> settings = Maps.newHashMap();
|
||||
settings.put(Environment.DIALECT, NomulusPostgreSQLDialect.class.getName());
|
||||
settings.put(Environment.URL, jdbcUrl);
|
||||
settings.put(Environment.USER, username);
|
||||
settings.put(Environment.PASS, password);
|
||||
settings.put(Environment.HBM2DDL_AUTO, "none");
|
||||
settings.put(Environment.SHOW_SQL, "true");
|
||||
settings.put(
|
||||
Environment.PHYSICAL_NAMING_STRATEGY, NomulusNamingStrategy.class.getCanonicalName());
|
||||
|
||||
try (StandardServiceRegistry registry =
|
||||
new StandardServiceRegistryBuilder().applySettings(settings).build()) {
|
||||
MetadataSources metadata = new MetadataSources(registry);
|
||||
|
||||
// Note that we need to also add all converters to the Hibernate context because
|
||||
// the entity class may use the customized type.
|
||||
Stream.concat(entityClasses.stream(), findAllConverters().stream())
|
||||
.forEach(metadata::addAnnotatedClass);
|
||||
|
||||
SchemaExport export = new SchemaExport();
|
||||
export.setHaltOnError(true);
|
||||
export.setFormat(true);
|
||||
export.setDelimiter(";");
|
||||
export.setOutputFile(outputFile.getAbsolutePath());
|
||||
export.createOnly(EnumSet.of(TargetType.SCRIPT), metadata.buildMetadata());
|
||||
}
|
||||
}
|
||||
|
||||
private ImmutableList<Class> findAllConverters() {
|
||||
ParsedPersistenceXmlDescriptor descriptor =
|
||||
PersistenceXmlParser.locatePersistenceUnits(new Properties()).stream()
|
||||
.filter(unit -> PersistenceModule.PERSISTENCE_UNIT_NAME.equals(unit.getName()))
|
||||
.findFirst()
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new IllegalArgumentException(
|
||||
String.format(
|
||||
"Could not find persistence unit with name %s",
|
||||
PersistenceModule.PERSISTENCE_UNIT_NAME)));
|
||||
return descriptor.getManagedClassNames().stream()
|
||||
.map(
|
||||
className -> {
|
||||
try {
|
||||
return Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
})
|
||||
.filter(AttributeConverter.class::isAssignableFrom)
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
}
|
||||
@@ -347,7 +347,7 @@ public class AuthenticatedRegistrarAccessor {
|
||||
|
||||
/** Exception thrown when the current user doesn't have access to the requested Registrar. */
|
||||
public static class RegistrarAccessDeniedException extends Exception {
|
||||
RegistrarAccessDeniedException(String message) {
|
||||
public RegistrarAccessDeniedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,6 +176,10 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
|
||||
this.completionTimestamp = toZonedDateTime(dateTime);
|
||||
}
|
||||
|
||||
public boolean isVerified() {
|
||||
return completionTimestamp != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
return new Builder(clone(this));
|
||||
|
||||
@@ -72,7 +72,7 @@ final class CreateDomainCommand extends CreateOrUpdateDomainCommand
|
||||
!force || forcePremiums,
|
||||
"Forced creates on premium domain(s) require --force_premiums");
|
||||
Money createCost = prices.getCreateCost();
|
||||
currency = createCost.getCurrencyUnit().getCurrencyCode();
|
||||
currency = createCost.getCurrencyUnit().getCode();
|
||||
cost = createCost.multipliedBy(period).getAmount().toString();
|
||||
System.out.printf(
|
||||
"NOTE: %s is premium at %s per year; sending total cost for %d year(s) of %s %s.\n",
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
// Copyright 2019 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.ui.server.registrar;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.net.HttpHeaders.X_FRAME_OPTIONS;
|
||||
import static google.registry.security.JsonResponseHelper.Status.SUCCESS;
|
||||
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_INTERNAL_SERVER_ERROR;
|
||||
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.model.registry.RegistryLockDao;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Method;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.RequestMethod;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.schema.domain.RegistryLock;
|
||||
import google.registry.security.JsonResponseHelper;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* Servlet that allows for getting locks for a particular registrar.
|
||||
*
|
||||
* <p>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}.
|
||||
*/
|
||||
@Action(
|
||||
service = Action.Service.DEFAULT,
|
||||
path = RegistryLockGetAction.PATH,
|
||||
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
||||
public final class RegistryLockGetAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/registry-lock-get";
|
||||
|
||||
private static final String LOCK_ENABLED_FOR_CONTACT_PARAM = "lockEnabledForContact";
|
||||
private static final String EMAIL_PARAM = "email";
|
||||
private static final String LOCKS_PARAM = "locks";
|
||||
private static final String FULLY_QUALIFIED_DOMAIN_NAME_PARAM = "fullyQualifiedDomainName";
|
||||
private static final String LOCKED_TIME_PARAM = "lockedTime";
|
||||
private static final String LOCKED_BY_PARAM = "lockedBy";
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
@VisibleForTesting Method method;
|
||||
private final Response response;
|
||||
private final AuthenticatedRegistrarAccessor registrarAccessor;
|
||||
@VisibleForTesting AuthResult authResult;
|
||||
@VisibleForTesting Optional<String> paramClientId;
|
||||
|
||||
@Inject
|
||||
RegistryLockGetAction(
|
||||
@RequestMethod Method method,
|
||||
Response response,
|
||||
AuthenticatedRegistrarAccessor registrarAccessor,
|
||||
AuthResult authResult,
|
||||
@Parameter(PARAM_CLIENT_ID) Optional<String> paramClientId) {
|
||||
this.method = method;
|
||||
this.response = response;
|
||||
this.registrarAccessor = registrarAccessor;
|
||||
this.authResult = authResult;
|
||||
this.paramClientId = paramClientId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
checkArgument(Method.GET.equals(method), "Only GET requests allowed");
|
||||
checkArgument(authResult.userAuthInfo().isPresent(), "User auth info must be present");
|
||||
checkArgument(paramClientId.isPresent(), "clientId must be present");
|
||||
response.setContentType(MediaType.JSON_UTF_8);
|
||||
response.setHeader(X_FRAME_OPTIONS, "SAMEORIGIN"); // Disallow iframing.
|
||||
response.setHeader("X-Ui-Compatible", "IE=edge"); // Ask IE not to be silly.
|
||||
|
||||
try {
|
||||
ImmutableMap<String, ?> resultMap = getLockedDomainsMap(paramClientId.get());
|
||||
ImmutableMap<String, ?> payload =
|
||||
JsonResponseHelper.create(SUCCESS, "Successful locks retrieval", resultMap);
|
||||
response.setPayload(GSON.toJson(payload));
|
||||
} catch (RegistrarAccessDeniedException e) {
|
||||
logger.atWarning().withCause(e).log(
|
||||
"User %s doesn't have access to this registrar", authResult.userIdForLogging());
|
||||
response.setStatus(SC_FORBIDDEN);
|
||||
} catch (Exception e) {
|
||||
logger.atWarning().withCause(e).log("Unexpected error when retrieving locks for a registrar");
|
||||
response.setStatus(SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private ImmutableMap<String, ?> getLockedDomainsMap(String clientId)
|
||||
throws RegistrarAccessDeniedException {
|
||||
// Note: admins always have access to the locks page
|
||||
checkArgument(authResult.userAuthInfo().isPresent(), "User auth info must be present");
|
||||
UserAuthInfo userAuthInfo = authResult.userAuthInfo().get();
|
||||
boolean isAdmin = userAuthInfo.isUserAdmin();
|
||||
Registrar registrar = getRegistrarAndVerifyLockAccess(clientId, isAdmin);
|
||||
User user = userAuthInfo.user();
|
||||
boolean isRegistryLockAllowed =
|
||||
isAdmin
|
||||
|| registrar.getContacts().stream()
|
||||
.filter(contact -> contact.getEmailAddress().equals(user.getEmail()))
|
||||
.findFirst()
|
||||
.map(RegistrarContact::isRegistryLockAllowed)
|
||||
.orElse(false);
|
||||
return ImmutableMap.of(
|
||||
LOCK_ENABLED_FOR_CONTACT_PARAM,
|
||||
isRegistryLockAllowed,
|
||||
EMAIL_PARAM,
|
||||
user.getEmail(),
|
||||
PARAM_CLIENT_ID,
|
||||
registrar.getClientId(),
|
||||
LOCKS_PARAM,
|
||||
getLockedDomains(clientId));
|
||||
}
|
||||
|
||||
private Registrar getRegistrarAndVerifyLockAccess(String clientId, boolean isAdmin)
|
||||
throws RegistrarAccessDeniedException {
|
||||
Registrar registrar = registrarAccessor.getRegistrar(clientId);
|
||||
checkArgument(
|
||||
isAdmin || registrar.isRegistryLockAllowed(),
|
||||
"Registry lock not allowed for this registrar");
|
||||
return registrar;
|
||||
}
|
||||
|
||||
private ImmutableList<ImmutableMap<String, ?>> getLockedDomains(String clientId) {
|
||||
ImmutableList<RegistryLock> locks =
|
||||
RegistryLockDao.getByRegistrarId(clientId).stream()
|
||||
.filter(RegistryLock::isVerified)
|
||||
.collect(toImmutableList());
|
||||
return locks.stream().map(this::lockToMap).collect(toImmutableList());
|
||||
}
|
||||
|
||||
private ImmutableMap<String, ?> lockToMap(RegistryLock lock) {
|
||||
return ImmutableMap.of(
|
||||
FULLY_QUALIFIED_DOMAIN_NAME_PARAM,
|
||||
lock.getDomainName(),
|
||||
LOCKED_TIME_PARAM,
|
||||
lock.getCompletionTimestamp().map(DateTime::toString).orElse(""),
|
||||
LOCKED_BY_PARAM,
|
||||
lock.isSuperuser() ? "admin" : lock.getRegistrarPocId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
|
||||
http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd"
|
||||
version="2.2">
|
||||
<embeddable class="org.joda.money.Money" access="FIELD">
|
||||
<attributes>
|
||||
<embedded name="money" access="FIELD"/>
|
||||
</attributes>
|
||||
</embeddable>
|
||||
<embeddable class="org.joda.money.BigMoney" access="FIELD">
|
||||
<attributes>
|
||||
<basic name="amount" access="FIELD"/>
|
||||
<basic name="currency" access="FIELD"/>
|
||||
</attributes>
|
||||
</embeddable>
|
||||
</entity-mappings>
|
||||
@@ -129,6 +129,7 @@ import google.registry.flows.domain.DomainFlowUtils.TrailingDashException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.UnexpectedClaimsNoticeException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.UnsupportedMarkTypeException;
|
||||
import google.registry.flows.domain.DomainPricingLogic.AllocationTokenInvalidForPremiumNameException;
|
||||
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException;
|
||||
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException;
|
||||
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException;
|
||||
@@ -1227,9 +1228,9 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
||||
.build());
|
||||
clock.advanceOneMilli();
|
||||
setEppInput("domain_create_premium_allocationtoken.xml");
|
||||
assertThat(assertThrows(IllegalArgumentException.class, this::runFlow))
|
||||
.hasMessageThat()
|
||||
.isEqualTo("A nonzero discount code cannot be applied to premium domains");
|
||||
assertAboutEppExceptions()
|
||||
.that(assertThrows(AllocationTokenInvalidForPremiumNameException.class, this::runFlow))
|
||||
.marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+61
-10
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.model.transaction;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.testcontainers.containers.PostgreSQLContainer.POSTGRESQL_PORT;
|
||||
|
||||
@@ -23,11 +24,19 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.io.Resources;
|
||||
import google.registry.persistence.HibernateSchemaExporter;
|
||||
import google.registry.persistence.PersistenceModule;
|
||||
import google.registry.testing.FakeClock;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -52,8 +61,8 @@ import org.testcontainers.containers.PostgreSQLContainer;
|
||||
* PostgreSQLContainer} to achieve test purpose.
|
||||
*/
|
||||
public class JpaTransactionManagerRule extends ExternalResource {
|
||||
private static final String SCHEMA_GOLDEN_SQL = "sql/schema/nomulus.golden.sql";
|
||||
private static final String DB_CLEANUP_SQL =
|
||||
private static final String GOLDEN_SCHEMA_SQL_PATH = "sql/schema/nomulus.golden.sql";
|
||||
private static final String DB_CLEANUP_SQL_PATH =
|
||||
"google/registry/model/transaction/cleanup_database.sql";
|
||||
private static final String MANAGEMENT_DB_NAME = "management";
|
||||
private static final String POSTGRES_DB_NAME = "postgres";
|
||||
@@ -65,6 +74,9 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
private final ImmutableMap userProperties;
|
||||
|
||||
private static final JdbcDatabaseContainer database = create();
|
||||
private static final HibernateSchemaExporter exporter =
|
||||
HibernateSchemaExporter.create(
|
||||
database.getJdbcUrl(), database.getUsername(), database.getPassword());
|
||||
private EntityManagerFactory emf;
|
||||
private JpaTransactionManager cachedTm;
|
||||
|
||||
@@ -86,8 +98,16 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
|
||||
@Override
|
||||
public void before() throws Exception {
|
||||
executeSql(MANAGEMENT_DB_NAME, DB_CLEANUP_SQL);
|
||||
executeSql(POSTGRES_DB_NAME, initScriptPath);
|
||||
executeSql(MANAGEMENT_DB_NAME, readSqlInClassPath(DB_CLEANUP_SQL_PATH));
|
||||
executeSql(POSTGRES_DB_NAME, readSqlInClassPath(initScriptPath));
|
||||
if (!extraEntityClasses.isEmpty()) {
|
||||
File tempSqlFile = File.createTempFile("tempSqlFile", ".sql");
|
||||
tempSqlFile.deleteOnExit();
|
||||
exporter.export(extraEntityClasses, tempSqlFile);
|
||||
executeSql(
|
||||
POSTGRES_DB_NAME,
|
||||
new String(Files.readAllBytes(tempSqlFile.toPath()), StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
ImmutableMap properties = PersistenceModule.providesDefaultDatabaseConfigs();
|
||||
if (!userProperties.isEmpty()) {
|
||||
@@ -96,7 +116,7 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
builder.putAll(userProperties);
|
||||
properties = builder.build();
|
||||
}
|
||||
|
||||
assertNormalActiveConnection();
|
||||
emf =
|
||||
createEntityManagerFactory(
|
||||
getJdbcUrlFor(POSTGRES_DB_NAME),
|
||||
@@ -114,14 +134,45 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
TransactionManagerFactory.jpaTm = cachedTm;
|
||||
if (emf != null) {
|
||||
emf.close();
|
||||
emf = null;
|
||||
}
|
||||
cachedTm = null;
|
||||
assertNormalActiveConnection();
|
||||
}
|
||||
|
||||
private void executeSql(String dbName, String sqlScriptPath) {
|
||||
try (Connection conn = createConnection(dbName)) {
|
||||
String sqlScript = Resources.toString(Resources.getResource(sqlScriptPath), Charsets.UTF_8);
|
||||
conn.createStatement().execute(sqlScript);
|
||||
/**
|
||||
* This function throws exception if it detects connection leak by checking the metadata table
|
||||
* pg_stat_activity.
|
||||
*/
|
||||
private void assertNormalActiveConnection() {
|
||||
try (Connection conn = createConnection(POSTGRES_DB_NAME);
|
||||
Statement statement = conn.createStatement()) {
|
||||
ResultSet rs =
|
||||
statement.executeQuery(
|
||||
"SELECT COUNT(1) FROM pg_stat_activity WHERE usename = '"
|
||||
+ database.getUsername()
|
||||
+ "'");
|
||||
rs.next();
|
||||
long activeConns = rs.getLong(1);
|
||||
// There should be only 1 active connection which is executing this query
|
||||
assertThat(activeConns).isEqualTo(1L);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String readSqlInClassPath(String sqlScriptPath) {
|
||||
try {
|
||||
return Resources.toString(Resources.getResource(sqlScriptPath), Charsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeSql(String dbName, String sqlScript) {
|
||||
try (Connection conn = createConnection(dbName);
|
||||
Statement statement = conn.createStatement()) {
|
||||
statement.execute(sqlScript);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -212,7 +263,7 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
/** Builds a {@link JpaTransactionManagerRule} instance. */
|
||||
public JpaTransactionManagerRule build() {
|
||||
if (initScript == null) {
|
||||
initScript = SCHEMA_GOLDEN_SQL;
|
||||
initScript = GOLDEN_SCHEMA_SQL_PATH;
|
||||
}
|
||||
return new JpaTransactionManagerRule(
|
||||
initScript,
|
||||
|
||||
-2
@@ -23,7 +23,6 @@ import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.PersistenceException;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -37,7 +36,6 @@ public class JpaTransactionManagerRuleTest {
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
|
||||
@@ -24,7 +24,6 @@ import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -38,7 +37,6 @@ public class BloomFilterConverterTest {
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
|
||||
@@ -21,7 +21,6 @@ import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -36,7 +35,6 @@ public class CreateAutoTimestampConverterTest {
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
|
||||
@@ -22,7 +22,6 @@ import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.PersistenceException;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -37,7 +36,6 @@ public class CurrencyUnitConverterTest {
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
@@ -50,7 +48,8 @@ public class CurrencyUnitConverterTest {
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery("SELECT currency FROM TestEntity WHERE name = 'id'")
|
||||
.createNativeQuery(
|
||||
"SELECT currency FROM \"TestEntity\" WHERE name = 'id'")
|
||||
.getResultList()))
|
||||
.containsExactly("EUR");
|
||||
TestEntity persisted =
|
||||
@@ -66,7 +65,7 @@ public class CurrencyUnitConverterTest {
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(
|
||||
"INSERT INTO TestEntity (name, currency) VALUES('id', 'XXXX')")
|
||||
"INSERT INTO \"TestEntity\" (name, currency) VALUES('id', 'XXXX')")
|
||||
.executeUpdate());
|
||||
PersistenceException thrown =
|
||||
assertThrows(
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright 2019 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;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
|
||||
/** Unit tests for {@link HibernateSchemaExporter}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class HibernateSchemaExporterTest {
|
||||
@ClassRule public static final PostgreSQLContainer database = new PostgreSQLContainer();
|
||||
private static HibernateSchemaExporter exporter;
|
||||
|
||||
@Rule public final TemporaryFolder tempFolder = new TemporaryFolder();
|
||||
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
exporter =
|
||||
HibernateSchemaExporter.create(
|
||||
database.getJdbcUrl(), database.getUsername(), database.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void export_succeeds() throws IOException {
|
||||
File sqlFile = tempFolder.newFile();
|
||||
exporter.export(ImmutableList.of(TestEntity.class), sqlFile);
|
||||
assertThat(Files.readAllBytes(sqlFile.toPath()))
|
||||
.isEqualTo(
|
||||
("\n"
|
||||
+ " create table \"TestEntity\" (\n"
|
||||
+ " name text not null,\n"
|
||||
+ " cu text,\n"
|
||||
+ " primary key (name)\n"
|
||||
+ " );\n")
|
||||
.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
|
||||
private static class TestEntity {
|
||||
@Id String name;
|
||||
|
||||
CurrencyUnit cu;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
// Copyright 2019 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;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.PostLoad;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/**
|
||||
* Unit tests for embeddable {@link Money}.
|
||||
*
|
||||
* <p>{@link Money} is a wrapper around {@link org.joda.money.BigMoney} which itself contains two
|
||||
* fields: a {@link BigDecimal} {@code amount} and a {@link CurrencyUnit} {@code currency}. When we
|
||||
* store an entity with a {@link Money} field, we would like to store it in two columns, for the
|
||||
* amount and the currency separately, so that it is easily queryable. This requires that we make
|
||||
* {@link Money} a nested embeddable object.
|
||||
*
|
||||
* <p>However becaues {@link Money} is not a class that we control, we cannot use annotation-based
|
||||
* mapping. Therefore there is no {@code JodaMoneyConverter} class. Instead, we define the mapping
|
||||
* in {@code META-INF/orm.xml}.
|
||||
*
|
||||
* <p>Also note that any entity that contains a {@link Money} should should implement a
|
||||
* {@link @PostLoad} callback that converts the amount in the {@link Money} to a scale that is
|
||||
* appropriate for the currency. This is espcially necessary for currencies like JPY where the scale
|
||||
* is 0, which is different from the default scale that {@link BigDecimal} is persisted in database.
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class JodaMoneyConverterTest {
|
||||
@Rule
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class, ComplexTestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
public void roundTripConversion() {
|
||||
Money money = Money.of(CurrencyUnit.USD, 100);
|
||||
TestEntity entity = new TestEntity(money);
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(entity));
|
||||
List<?> result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(
|
||||
"SELECT amount, currency FROM TestEntity WHERE name = 'id'")
|
||||
.getResultList());
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertThat(Arrays.asList((Object[]) result.get(0)))
|
||||
.containsExactly(
|
||||
BigDecimal.valueOf(100).setScale(CurrencyUnit.USD.getDecimalPlaces()), "USD")
|
||||
.inOrder();
|
||||
TestEntity persisted =
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "id"));
|
||||
assertThat(persisted.money).isEqualTo(money);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundTripConversionWithComplexEntity() {
|
||||
Money myMoney = Money.of(CurrencyUnit.USD, 100);
|
||||
Money yourMoney = Money.of(CurrencyUnit.GBP, 80);
|
||||
ImmutableMap<String, Money> moneyMap =
|
||||
ImmutableMap.of(
|
||||
"uno", Money.of(CurrencyUnit.EUR, 500),
|
||||
"dos", Money.ofMajor(CurrencyUnit.JPY, 2000),
|
||||
"tres", Money.of(CurrencyUnit.GBP, 20));
|
||||
ComplexTestEntity entity = new ComplexTestEntity(moneyMap, myMoney, yourMoney);
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(entity));
|
||||
List<?> result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(
|
||||
"SELECT my_amount, my_currency, your_amount, your_currency FROM"
|
||||
+ " ComplexTestEntity WHERE name = 'id'")
|
||||
.getResultList());
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertThat(Arrays.asList((Object[]) result.get(0)))
|
||||
.containsExactly(
|
||||
BigDecimal.valueOf(100).setScale(2), "USD", BigDecimal.valueOf(80).setScale(2), "GBP")
|
||||
.inOrder();
|
||||
result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(
|
||||
"SELECT map_amount, map_currency FROM MoneyMap"
|
||||
+ " WHERE entity_name = 'id' AND map_key = 'dos'")
|
||||
.getResultList());
|
||||
ComplexTestEntity persisted =
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().find(ComplexTestEntity.class, "id"));
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
|
||||
// Note that the amount has two decimal places even though JPY is supposed to have scale 0.
|
||||
// This is due to the unfournate fact that we need to accommodate differet currencies stored
|
||||
// in the same table so that the scale has to be set to the largest (2). When a Money field is
|
||||
// persisted in an entity, the entity should always have a @PostLoad callback to convert the
|
||||
// Money to the correct scale.
|
||||
assertThat(Arrays.asList((Object[]) result.get(0)))
|
||||
.containsExactly(BigDecimal.valueOf(2000).setScale(2), "JPY")
|
||||
.inOrder();
|
||||
// Make sure that the loaded entity contains the fields exactly as they are persisted.
|
||||
assertThat(persisted.myMoney).isEqualTo(myMoney);
|
||||
assertThat(persisted.yourMoney).isEqualTo(yourMoney);
|
||||
assertThat(persisted.moneyMap).containsExactlyEntriesIn(moneyMap);
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
|
||||
public static class TestEntity extends ImmutableObject {
|
||||
|
||||
@Id String name = "id";
|
||||
|
||||
Money money;
|
||||
|
||||
public TestEntity() {}
|
||||
|
||||
TestEntity(Money money) {
|
||||
this.money = money;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "ComplexTestEntity") // Override entity name to avoid the nested class reference.
|
||||
// This entity is used to test column override for embedded fields and collections.
|
||||
public static class ComplexTestEntity extends ImmutableObject {
|
||||
|
||||
// After the entity is loaded from the database, go through the money map and make sure that
|
||||
// the scale is consistent with the currency. This is necessary for currency like JPY where
|
||||
// the scale is 0 but the amount is persisteted as BigDecimal with scale 2.
|
||||
@PostLoad
|
||||
void setCurrencyScale() {
|
||||
moneyMap
|
||||
.entrySet()
|
||||
.forEach(
|
||||
entry -> {
|
||||
Money money = entry.getValue();
|
||||
if (!money.toBigMoney().isCurrencyScale()) {
|
||||
CurrencyUnit currency = money.getCurrencyUnit();
|
||||
BigDecimal amount = money.getAmount().setScale(currency.getDecimalPlaces());
|
||||
entry.setValue(Money.of(currency, amount));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Id String name = "id";
|
||||
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(name = "MoneyMap", joinColumns = @JoinColumn(name = "entity_name"))
|
||||
@MapKeyColumn(name = "map_key")
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "value.money.amount", column = @Column(name = "map_amount")),
|
||||
@AttributeOverride(name = "value.money.currency", column = @Column(name = "map_currency"))
|
||||
})
|
||||
Map<String, Money> moneyMap;
|
||||
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "money.amount", column = @Column(name = "my_amount")),
|
||||
@AttributeOverride(name = "money.currency", column = @Column(name = "my_currency"))
|
||||
})
|
||||
Money myMoney;
|
||||
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "money.amount", column = @Column(name = "your_amount")),
|
||||
@AttributeOverride(name = "money.currency", column = @Column(name = "your_currency"))
|
||||
})
|
||||
Money yourMoney;
|
||||
|
||||
public ComplexTestEntity() {}
|
||||
|
||||
ComplexTestEntity(ImmutableMap<String, Money> moneyMap, Money myMoney, Money yourMoney) {
|
||||
this.moneyMap = moneyMap;
|
||||
this.myMoney = myMoney;
|
||||
this.yourMoney = yourMoney;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -35,7 +34,6 @@ public class UpdateAutoTimestampConverterTest {
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.time.Instant;
|
||||
import java.time.ZonedDateTime;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -38,7 +37,6 @@ public class ZonedDateTimeConverterTest {
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
private final ZonedDateTimeConverter converter = new ZonedDateTimeConverter();
|
||||
|
||||
@@ -21,9 +21,11 @@ import google.registry.model.transaction.JpaTransactionManagerRuleTest;
|
||||
import google.registry.persistence.BloomFilterConverterTest;
|
||||
import google.registry.persistence.CreateAutoTimestampConverterTest;
|
||||
import google.registry.persistence.CurrencyUnitConverterTest;
|
||||
import google.registry.persistence.JodaMoneyConverterTest;
|
||||
import google.registry.persistence.UpdateAutoTimestampConverterTest;
|
||||
import google.registry.persistence.ZonedDateTimeConverterTest;
|
||||
import google.registry.schema.tld.PremiumListDaoTest;
|
||||
import google.registry.ui.server.registrar.RegistryLockGetActionTest;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
@@ -44,10 +46,12 @@ import org.junit.runners.Suite.SuiteClasses;
|
||||
ClaimsListDaoTest.class,
|
||||
CreateAutoTimestampConverterTest.class,
|
||||
CurrencyUnitConverterTest.class,
|
||||
JodaMoneyConverterTest.class,
|
||||
JpaTransactionManagerImplTest.class,
|
||||
JpaTransactionManagerRuleTest.class,
|
||||
PremiumListDaoTest.class,
|
||||
RegistryLockDaoTest.class,
|
||||
RegistryLockGetActionTest.class,
|
||||
UpdateAutoTimestampConverterTest.class,
|
||||
ZonedDateTimeConverterTest.class
|
||||
})
|
||||
|
||||
@@ -82,7 +82,8 @@ public final class RegistryTestServer {
|
||||
route("/registrar-create", FrontendServlet.class),
|
||||
route("/registrar-ote-setup", FrontendServlet.class),
|
||||
route("/registrar-ote-status", FrontendServlet.class),
|
||||
route("/registrar-settings", FrontendServlet.class));
|
||||
route("/registrar-settings", FrontendServlet.class),
|
||||
route("/registry-lock-get", FrontendServlet.class));
|
||||
|
||||
private static final ImmutableList<Class<? extends Filter>> FILTERS = ImmutableList.of(
|
||||
ObjectifyFilter.class,
|
||||
|
||||
+256
@@ -0,0 +1,256 @@
|
||||
// Copyright 2019 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.ui.server.registrar;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.OWNER;
|
||||
import static google.registry.testing.AppEngineRule.makeRegistrar2;
|
||||
import static google.registry.testing.AppEngineRule.makeRegistrarContact3;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
|
||||
import com.google.api.client.http.HttpStatusCodes;
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.model.registry.RegistryLockDao;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import google.registry.request.Action.Method;
|
||||
import google.registry.request.auth.AuthLevel;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.schema.domain.RegistryLock;
|
||||
import google.registry.schema.domain.RegistryLock.Action;
|
||||
import google.registry.testing.AppEngineRule;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
/** Unit tests for {@link RegistryLockGetAction}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public final class RegistryLockGetActionTest {
|
||||
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
@Rule public final AppEngineRule appEngineRule = AppEngineRule.builder().withDatastore().build();
|
||||
|
||||
@Rule
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder().build();
|
||||
|
||||
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
|
||||
|
||||
private final FakeResponse response = new FakeResponse();
|
||||
private final User user = new User("Marla.Singer@crr.com", "gmail.com", "12345");
|
||||
|
||||
private AuthResult authResult;
|
||||
private AuthenticatedRegistrarAccessor accessor;
|
||||
private RegistryLockGetAction action;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
jpaTmRule.getTxnClock().setTo(DateTime.parse("2000-06-08T22:00:00.0Z"));
|
||||
authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
|
||||
accessor =
|
||||
AuthenticatedRegistrarAccessor.createForTesting(
|
||||
ImmutableSetMultimap.of(
|
||||
"TheRegistrar", OWNER,
|
||||
"NewRegistrar", OWNER));
|
||||
action =
|
||||
new RegistryLockGetAction(
|
||||
Method.GET, response, accessor, authResult, Optional.of("TheRegistrar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_retrievesLocks() {
|
||||
RegistryLock regularLock =
|
||||
new RegistryLock.Builder()
|
||||
.setRepoId("repoId")
|
||||
.setDomainName("example.test")
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setAction(Action.LOCK)
|
||||
.setVerificationCode(UUID.randomUUID().toString())
|
||||
.setRegistrarPocId("johndoe@theregistrar.com")
|
||||
.setCompletionTimestamp(jpaTmRule.getTxnClock().nowUtc())
|
||||
.build();
|
||||
jpaTmRule.getTxnClock().advanceOneMilli();
|
||||
RegistryLock adminLock =
|
||||
new RegistryLock.Builder()
|
||||
.setRepoId("repoId")
|
||||
.setDomainName("adminexample.test")
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setAction(Action.LOCK)
|
||||
.setVerificationCode(UUID.randomUUID().toString())
|
||||
.isSuperuser(true)
|
||||
.setCompletionTimestamp(jpaTmRule.getTxnClock().nowUtc())
|
||||
.build();
|
||||
RegistryLock incompleteLock =
|
||||
new RegistryLock.Builder()
|
||||
.setRepoId("repoId")
|
||||
.setDomainName("incomplete.test")
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setAction(Action.LOCK)
|
||||
.setVerificationCode(UUID.randomUUID().toString())
|
||||
.setRegistrarPocId("johndoe@theregistrar.com")
|
||||
.build();
|
||||
|
||||
RegistryLockDao.save(regularLock);
|
||||
RegistryLockDao.save(adminLock);
|
||||
RegistryLockDao.save(incompleteLock);
|
||||
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
|
||||
assertThat(GSON.fromJson(response.getPayload(), Map.class))
|
||||
.containsExactly(
|
||||
"status", "SUCCESS",
|
||||
"message", "Successful locks retrieval",
|
||||
"results",
|
||||
ImmutableList.of(
|
||||
ImmutableMap.of(
|
||||
"lockEnabledForContact", true,
|
||||
"email", "Marla.Singer@crr.com",
|
||||
"clientId", "TheRegistrar",
|
||||
"locks",
|
||||
ImmutableList.of(
|
||||
ImmutableMap.of(
|
||||
"fullyQualifiedDomainName", "example.test",
|
||||
"lockedTime", "2000-06-08T22:00:00.000Z",
|
||||
"lockedBy", "johndoe@theregistrar.com"),
|
||||
ImmutableMap.of(
|
||||
"fullyQualifiedDomainName", "adminexample.test",
|
||||
"lockedTime", "2000-06-08T22:00:00.001Z",
|
||||
"lockedBy", "admin")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_invalidMethod() {
|
||||
action.method = Method.POST;
|
||||
assertThat(assertThrows(IllegalArgumentException.class, action::run))
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Only GET requests allowed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_noAuthInfo() {
|
||||
action.authResult = AuthResult.NOT_AUTHENTICATED;
|
||||
assertThat(assertThrows(IllegalArgumentException.class, action::run))
|
||||
.hasMessageThat()
|
||||
.isEqualTo("User auth info must be present");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_noClientId() {
|
||||
action.paramClientId = Optional.empty();
|
||||
assertThat(assertThrows(IllegalArgumentException.class, action::run))
|
||||
.hasMessageThat()
|
||||
.isEqualTo("clientId must be present");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_noRegistrarAccess() {
|
||||
accessor = AuthenticatedRegistrarAccessor.createForTesting(ImmutableSetMultimap.of());
|
||||
action =
|
||||
new RegistryLockGetAction(
|
||||
Method.GET, response, accessor, authResult, Optional.of("TheRegistrar"));
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_readOnlyAccessForOtherUsers() {
|
||||
// If lock is not enabled for a user, this should be read-only
|
||||
persistResource(
|
||||
makeRegistrarContact3().asBuilder().setAllowedToSetRegistryLockPassword(true).build());
|
||||
action.run();
|
||||
assertThat(GSON.fromJson(response.getPayload(), Map.class).get("results"))
|
||||
.isEqualTo(
|
||||
ImmutableList.of(
|
||||
ImmutableMap.of(
|
||||
"lockEnabledForContact",
|
||||
false,
|
||||
"email",
|
||||
"Marla.Singer@crr.com",
|
||||
"clientId",
|
||||
"TheRegistrar",
|
||||
"locks",
|
||||
ImmutableList.of())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_lockAllowedForAdmin() throws Exception {
|
||||
// Locks are allowed for admins even when they're not enabled for the registrar
|
||||
persistResource(makeRegistrar2().asBuilder().setRegistryLockAllowed(false).build());
|
||||
authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, true));
|
||||
action =
|
||||
new RegistryLockGetAction(
|
||||
Method.GET, response, accessor, authResult, Optional.of("TheRegistrar"));
|
||||
action.run();
|
||||
assertThat(GSON.fromJson(response.getPayload(), Map.class).get("results"))
|
||||
.isEqualTo(
|
||||
ImmutableList.of(
|
||||
ImmutableMap.of(
|
||||
"lockEnabledForContact",
|
||||
true,
|
||||
"email",
|
||||
"Marla.Singer@crr.com",
|
||||
"clientId",
|
||||
"TheRegistrar",
|
||||
"locks",
|
||||
ImmutableList.of())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_lockNotAllowedForRegistrar() {
|
||||
// The UI shouldn't be making requests where lock isn't enabled for this registrar
|
||||
action =
|
||||
new RegistryLockGetAction(
|
||||
Method.GET, response, accessor, authResult, Optional.of("NewRegistrar"));
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_accessDenied() {
|
||||
accessor = AuthenticatedRegistrarAccessor.createForTesting(ImmutableSetMultimap.of());
|
||||
action =
|
||||
new RegistryLockGetAction(
|
||||
Method.GET, response, accessor, authResult, Optional.of("TheRegistrar"));
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_badRegistrar() {
|
||||
action =
|
||||
new RegistryLockGetAction(
|
||||
Method.GET, response, accessor, authResult, Optional.of("SomeBadRegistrar"));
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
|
||||
}
|
||||
}
|
||||
@@ -5,3 +5,4 @@ PATH CLASS METHODS OK AUTH_METHODS
|
||||
/registrar-ote-setup ConsoleOteSetupAction POST,GET n INTERNAL,API,LEGACY NONE PUBLIC
|
||||
/registrar-ote-status OteStatusAction POST n API,LEGACY USER PUBLIC
|
||||
/registrar-settings RegistrarSettingsAction POST n API,LEGACY USER PUBLIC
|
||||
/registry-lock-get RegistryLockGetAction GET n API,LEGACY USER PUBLIC
|
||||
|
||||
+1
-1
@@ -120,7 +120,7 @@ ext {
|
||||
'org.hamcrest:hamcrest-core:1.3',
|
||||
'org.hamcrest:hamcrest-library:1.3',
|
||||
'org.hibernate:hibernate-hikaricp:5.4.4.Final',
|
||||
'org.joda:joda-money:0.10.0',
|
||||
'org.joda:joda-money:1.0.1',
|
||||
'org.json:json:20160810',
|
||||
'org.mockito:mockito-core:2.25.0',
|
||||
'org.mortbay.jetty:jetty:6.1.26',
|
||||
|
||||
@@ -302,6 +302,7 @@ An EPP flow that creates a new domain resource.
|
||||
* The current registry phase allows registrations only with signed marks.
|
||||
* The current registry phase does not allow for general registrations.
|
||||
* Signed marks are only allowed during sunrise.
|
||||
* An allocation token was provided that is invalid for premium domains.
|
||||
* 2003
|
||||
* The provided mark does not match the desired domain label.
|
||||
* Fees must be explicitly acknowledged when creating domains during the
|
||||
|
||||
@@ -240,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -228,7 +228,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -240,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -240,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -240,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -228,7 +228,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -240,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -240,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -203,7 +203,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -203,7 +203,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -203,7 +203,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -203,7 +203,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -203,7 +203,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -203,7 +203,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -203,7 +203,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -203,7 +203,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -240,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -228,7 +228,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -240,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -240,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
Reference in New Issue
Block a user