1
0
mirror of https://github.com/google/nomulus synced 2026-07-07 08:36:50 +00:00

Compare commits

...

9 Commits

Author SHA1 Message Date
Lai Jiang e88ff77ecb Harmonize http status code usage (#2451)
Given that we run servlets, it makes sense to always use the status
code contants from the servlet class.
2024-05-24 18:46:37 +00:00
sarahcaseybot 0781010b16 Create a load testing EPP client (#2415)
* Create a load testing EPP client.

This code is mostly based off of what was used for a past EPP load testing client that can be found in Google3 at https://source.corp.google.com/piper///depot/google3/experimental/users/jianglai/proxy/java/google/registry/proxy/client/

I modified the old client to be open-source friendly and use Gradle.

For now, this only performs a login and logout command, I will further expand on this in later PRs to add other EPP commands so that we can truly load test the system.

* Small changes

* Remove unnecessary build dep

* Add gradle build tasks

* Small fixes

* Add an instances setUp and cleanUp script

* More modifications to instance setup scripts

* change to ubuntu instance

* Add comment to make ssh work
2024-05-23 21:37:34 +00:00
Pavlo Tkach ab4bac05d1 Replace RegistryTestServerMain start address with ipv6 loopback (#2448) 2024-05-21 19:00:25 +00:00
Pavlo Tkach 8e22ce7c70 Add phone and fax number to console whois endpoint (#2447) 2024-05-20 20:32:23 +00:00
Lai Jiang d96a5547ce Store stack trace in a separate filed during logging (#2444)
For reasons unclear to me, if the stack trace is appended directly to
the message, the log entry will be lumped together with following logs
on GKE.

Also updated the GKE service account for Nomulus in the manifest so we
can use workload identity just for Nomulus, not other pods on the same
cluster.
2024-05-20 16:17:56 +00:00
Pavlo Tkach 05b43965d1 Fix console EPP password form, minor adjustments (#2445) 2024-05-17 18:44:44 +00:00
gbrodman 43000a5f80 Refactor common exception handling in ConsoleApiAction (#2443)
There are a bunch of cases where we want common exception handling and
it's annoying to have to deal with the common "set failed response and
make sure to return" a bunch of times.

This allows us to break up request methods more easily, since we can now
often throw exceptions that will break all the way back up to
ConsoleApiAction. Previously, any error handling had to exist in the
primary handler method so it could return.
2024-05-16 18:29:14 +00:00
Pavlo Tkach a66b9ea749 Add OTE registrars to console /registrars response (#2440) 2024-05-16 14:49:32 +00:00
sarahcaseybot 36a660a8ad Remove createBillingCost columns from db schema (#2438) 2024-05-15 18:19:36 +00:00
57 changed files with 3275 additions and 2507 deletions
+11 -18
View File
@@ -100,12 +100,12 @@ PRESUBMITS = {
{"node_modules/"}, REQUIRED):
"Source files must end in a newline.",
# System.(out|err).println should only appear in tools/
# System.(out|err).println should only appear in tools/ or load-testing/
PresubmitCheck(
r".*\bSystem\.(out|err)\.print", "java", {
"StackdriverDashboardBuilder.java", "/tools/", "/example/",
"RegistryTestServerMain.java", "TestServerExtension.java",
"FlowDocumentationTool.java"
"/load-testing/", "RegistryTestServerMain.java",
"TestServerExtension.java", "FlowDocumentationTool.java"
}):
"System.(out|err).println is only allowed in tools/ packages. Please "
"use a logger instead.",
@@ -173,23 +173,11 @@ PRESUBMITS = {
):
"JavaScript files should not include console logging.",
PresubmitCheck(
r".*org\.testcontainers\.shaded.*",
r".*\nimport (static )?.*\.shaded\..*",
"java",
{"/node_modules/"},
):
"Do not use shaded dependencies from testcontainers.",
PresubmitCheck(
r".*autovalue\.shaded.*",
"java",
{"/node_modules/"},
):
"Do not use shaded dependencies from autovalue.",
PresubmitCheck(
r".*avro\.shaded.*",
"java",
{"/node_modules/"},
):
"Do not use shaded dependencies from avro.",
"Do not use shaded dependencies",
PresubmitCheck(
r".*com\.google\.common\.truth\.Truth8.*",
"java",
@@ -202,7 +190,12 @@ PRESUBMITS = {
{"/node_modules/", "JpaTransactionManagerImpl.java"},
):
"Do not use java.util.Date. Use classes in java.time package instead.",
PresubmitCheck(
r".*com\.google\.api\.client\.http\.HttpStatusCodes.*",
"java",
{"/node_modules/"},
):
"Use status code from jakarta.servlet.http.HttpServletResponse.",
}
# Note that this regex only works for one kind of Flyway file. If we want to
+83 -14
View File
@@ -18,7 +18,6 @@
"@angular/platform-browser": "^17.3.5",
"@angular/platform-browser-dynamic": "^17.3.5",
"@angular/router": "^17.3.5",
"express": "^4.16.4",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.2"
@@ -5745,6 +5744,7 @@
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
"dev": true,
"dependencies": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
@@ -5983,7 +5983,8 @@
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
"dev": true
},
"node_modules/array-union": {
"version": "2.1.0",
@@ -6253,6 +6254,7 @@
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"dev": true,
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
@@ -6276,6 +6278,7 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"dependencies": {
"ms": "2.0.0"
}
@@ -6283,7 +6286,8 @@
"node_modules/body-parser/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
},
"node_modules/bonjour-service": {
"version": "1.2.1",
@@ -6397,6 +6401,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -6459,6 +6464,7 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"dev": true,
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@@ -6968,6 +6974,7 @@
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
"dev": true,
"dependencies": {
"safe-buffer": "5.2.1"
},
@@ -6979,6 +6986,7 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -7001,7 +7009,8 @@
"node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
"dev": true
},
"node_modules/copy-anything": {
"version": "2.0.6",
@@ -7414,6 +7423,7 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dev": true,
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@@ -7448,6 +7458,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -7465,6 +7476,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"dev": true,
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
@@ -7630,7 +7642,8 @@
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"dev": true
},
"node_modules/ejs": {
"version": "3.1.10",
@@ -7672,6 +7685,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -7822,6 +7836,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"dev": true,
"dependencies": {
"get-intrinsic": "^1.2.4"
},
@@ -7833,6 +7848,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"engines": {
"node": ">= 0.4"
}
@@ -7906,7 +7922,8 @@
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"dev": true
},
"node_modules/escape-string-regexp": {
"version": "1.0.5",
@@ -8336,6 +8353,7 @@
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -8388,6 +8406,7 @@
"version": "4.19.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
"dev": true,
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
@@ -8429,6 +8448,7 @@
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -8437,6 +8457,7 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"dependencies": {
"ms": "2.0.0"
}
@@ -8445,6 +8466,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
"dev": true,
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
@@ -8461,12 +8483,14 @@
"node_modules/express/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
},
"node_modules/express/node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -8787,6 +8811,7 @@
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -8808,6 +8833,7 @@
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -8874,6 +8900,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -8900,6 +8927,7 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"dev": true,
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
@@ -9028,6 +9056,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"dev": true,
"dependencies": {
"get-intrinsic": "^1.1.3"
},
@@ -9066,6 +9095,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dev": true,
"dependencies": {
"es-define-property": "^1.0.0"
},
@@ -9077,6 +9107,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
@@ -9088,6 +9119,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
@@ -9099,6 +9131,7 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.2"
},
@@ -9226,6 +9259,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"dev": true,
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
@@ -9241,6 +9275,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -9328,6 +9363,7 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dev": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
@@ -9463,7 +9499,8 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"node_modules/ini": {
"version": "4.1.2",
@@ -10872,6 +10909,7 @@
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -10891,7 +10929,8 @@
"node_modules/merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
"dev": true
},
"node_modules/merge-stream": {
"version": "2.0.0",
@@ -10912,6 +10951,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -10957,6 +10997,7 @@
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -10965,6 +11006,7 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
"dependencies": {
"mime-db": "1.52.0"
},
@@ -11325,6 +11367,7 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -11850,6 +11893,7 @@
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -11864,6 +11908,7 @@
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
"dev": true,
"dependencies": {
"ee-first": "1.1.1"
},
@@ -12238,6 +12283,7 @@
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -12303,7 +12349,8 @@
"node_modules/path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
"dev": true
},
"node_modules/path-type": {
"version": "4.0.0",
@@ -12679,6 +12726,7 @@
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"dev": true,
"dependencies": {
"forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
@@ -12691,6 +12739,7 @@
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
"dev": true,
"engines": {
"node": ">= 0.10"
}
@@ -12730,6 +12779,7 @@
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
"dev": true,
"dependencies": {
"side-channel": "^1.0.4"
},
@@ -12773,6 +12823,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -12781,6 +12832,7 @@
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"dev": true,
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
@@ -13189,6 +13241,7 @@
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true,
"funding": [
{
"type": "github",
@@ -13207,7 +13260,8 @@
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
"node_modules/safevalues": {
"version": "0.3.4",
@@ -13353,6 +13407,7 @@
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
"dev": true,
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
@@ -13376,6 +13431,7 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"dependencies": {
"ms": "2.0.0"
}
@@ -13383,12 +13439,14 @@
"node_modules/send/node_modules/debug/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
},
"node_modules/send/node_modules/mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"dev": true,
"bin": {
"mime": "cli.js"
},
@@ -13399,12 +13457,14 @@
"node_modules/send/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"node_modules/send/node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -13491,6 +13551,7 @@
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
"dev": true,
"dependencies": {
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
@@ -13505,6 +13566,7 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"dev": true,
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
@@ -13520,7 +13582,8 @@
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"dev": true
},
"node_modules/shallow-clone": {
"version": "3.0.1",
@@ -13568,6 +13631,7 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
@@ -14338,6 +14402,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"dev": true,
"engines": {
"node": ">=0.6"
}
@@ -14424,6 +14489,7 @@
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"dev": true,
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
@@ -14566,6 +14632,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -14619,6 +14686,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"dev": true,
"engines": {
"node": ">= 0.4.0"
}
@@ -14658,6 +14726,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -14,6 +14,7 @@
import { Component, computed } from '@angular/core';
import { RegistrarService } from '../registrar/registrar.service';
import { MatSnackBar } from '@angular/material/snack-bar';
@Component({
selector: 'app-billingInfo',
@@ -22,20 +23,25 @@ import { RegistrarService } from '../registrar/registrar.service';
})
export class BillingInfoComponent {
public static PATH = 'billingInfo';
constructor(public registrarService: RegistrarService) {}
constructor(
public registrarService: RegistrarService,
private _snackBar: MatSnackBar
) {}
driveFolderUrl = computed<string>(() => {
if (this.registrarService.registrar()?.driveFolderId) {
return `https://drive.google.com/drive/folders/${
return (
'https://drive.google.com/drive/folders/' +
this.registrarService.registrar()?.driveFolderId
}`;
);
}
return '';
});
openBillingDetails(e: MouseEvent) {
if (!this.driveFolderUrl()) {
if (!this.registrarService.registrar()?.driveFolderId) {
e.preventDefault();
this._snackBar.open('Billing Folder ID has not been assigned');
}
}
}
@@ -26,7 +26,7 @@
}
&-driveId {
min-width: 200px;
word-break: break-all;
word-break: break-word;
}
&-registryLockAllowed {
max-width: 80px;
@@ -51,10 +51,12 @@ export const columns = [
columnDef: 'billingAccountMap',
header: 'Billing Accounts',
cell: (record: Registrar) =>
// @ts-ignore - completely legit line, but TS keeps complaining
`${Object.entries(record.billingAccountMap).reduce((acc, [key, val]) => {
return `${acc}${key}=${val}<br/>`;
}, '')}`,
`${Object.entries(record.billingAccountMap || {}).reduce(
(acc, [key, val]) => {
return `${acc}${key}=${val}<br/>`;
},
''
)}`,
},
{
columnDef: 'registryLockAllowed',
@@ -71,7 +71,7 @@ export default class ContactComponent {
effect(() => {
if (this.contactService.contacts()) {
this.dataSource = new MatTableDataSource<ViewReadyContact>(
this.contactService.contacts().map(contactTypeToViewReadyContact)
this.contactService.contacts()
);
}
});
@@ -37,7 +37,7 @@ export default class WhoisComponent {
result += `${registrar?.localizedAddress?.state} `;
}
if (registrar?.localizedAddress?.countryCode) {
result += registrar?.localizedAddress?.countryCode;
result += `${registrar?.localizedAddress?.countryCode} `;
}
if (registrar?.localizedAddress?.zip) {
result += registrar?.localizedAddress?.zip;
+1 -1
View File
@@ -63,7 +63,7 @@ body {
.console-app__list-value {
font-size: 14px;
white-space: pre-line;
word-break: break-all;
word-break: break-word;
color: var(--text);
}
}
@@ -23,9 +23,9 @@ import static google.registry.model.tld.label.ReservedList.loadReservedLists;
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static java.nio.charset.StandardCharsets.US_ASCII;
import com.google.api.client.http.HttpStatusCodes;
import com.google.cloud.storage.BlobId;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
@@ -190,7 +190,7 @@ public class UploadBsaUnavailableDomainsAction implements Runnable {
return true;
} catch (IOException e) {
logger.atSevere().withCause(e).log("Error while attempting to upload to BSA, aborting.");
response.setStatus(HttpStatusCodes.STATUS_CODE_SERVER_ERROR);
response.setStatus(SC_INTERNAL_SERVER_ERROR);
response.setPayload("Error while attempting to upload to BSA: " + e.getMessage());
return false;
}
@@ -14,11 +14,11 @@
package google.registry.rdap;
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_OK;
import static com.google.common.net.HttpHeaders.ACCEPT_ENCODING;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.UrlConnectionUtils.gUnzipBytes;
import static google.registry.request.UrlConnectionUtils.isGZipped;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.ImmutableMap;
@@ -114,7 +114,7 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
connection.setRequestProperty(ACCEPT_ENCODING, "gzip");
String csvString;
try {
if (connection.getResponseCode() != STATUS_CODE_OK) {
if (connection.getResponseCode() != SC_OK) {
throw new UrlConnectionException("Failed to load RDAP base URLs from ICANN", connection);
}
// With GZIP encoding header in the request (see above) ICANN had still sent response in plain
@@ -14,12 +14,12 @@
package google.registry.rde;
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_BAD_REQUEST;
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_OK;
import static google.registry.request.UrlConnectionUtils.getResponseBytes;
import static google.registry.request.UrlConnectionUtils.setBasicAuth;
import static google.registry.request.UrlConnectionUtils.setPayload;
import static google.registry.util.DomainNameUtils.canonicalizeHostname;
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.api.client.http.HttpMethods;
@@ -85,7 +85,7 @@ public class RdeReporter {
try {
responseCode = connection.getResponseCode();
if (responseCode != STATUS_CODE_OK && responseCode != STATUS_CODE_BAD_REQUEST) {
if (responseCode != SC_OK && responseCode != SC_BAD_REQUEST) {
logger.atWarning().log("Connection to RDE report server failed: %d", responseCode);
throw new UrlConnectionException("PUT failed", connection);
}
@@ -96,7 +96,7 @@ public class RdeReporter {
// We know that an HTTP 200 response can only contain a result code of
// 1000 (i. e. success), there is no need to parse it.
if (responseCode != STATUS_CODE_OK) {
if (responseCode != SC_OK) {
XjcIirdeaResult result = parseResult(responseBytes);
logger.atWarning().log(
"Rejected when trying to PUT RDE report to ICANN server: %d %s\n%s",
@@ -14,10 +14,10 @@
package google.registry.reporting.icann;
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_OK;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.net.MediaType.CSV_UTF_8;
import static google.registry.model.tld.Tlds.assertTldExists;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import com.google.api.client.http.HttpMethods;
import com.google.common.base.Ascii;
@@ -95,7 +95,7 @@ public class IcannHttpReporter {
try {
responseCode = connection.getResponseCode();
content = UrlConnectionUtils.getResponseBytes(connection);
if (responseCode != STATUS_CODE_OK) {
if (responseCode != SC_OK) {
XjcIirdeaResult result = parseResult(content);
logger.atWarning().log(
"PUT rejected, status code %s:\n%s\n%s",
@@ -15,10 +15,17 @@
package google.registry.ui.server.console;
import static google.registry.request.Action.Method.GET;
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.base.Throwables;
import com.google.common.flogger.FluentLogger;
import google.registry.model.console.ConsolePermission;
import google.registry.model.console.GlobalRole;
import google.registry.model.console.User;
import google.registry.request.HttpException;
import google.registry.request.auth.AuthResult;
import google.registry.security.XsrfTokenManager;
import google.registry.ui.server.registrar.ConsoleApiParams;
@@ -31,6 +38,9 @@ import java.util.Optional;
/** Base class for handling Console API requests */
public abstract class ConsoleApiAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
protected ConsoleApiParams consoleApiParams;
public ConsoleApiAction(ConsoleApiParams consoleApiParams) {
@@ -43,7 +53,7 @@ public abstract class ConsoleApiAction implements Runnable {
AuthResult authResult = consoleApiParams.authResult();
if (authResult.userAuthInfo().isEmpty()
|| authResult.userAuthInfo().get().consoleUser().isEmpty()) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
consoleApiParams.response().setStatus(SC_UNAUTHORIZED);
return;
}
User user = consoleApiParams.authResult().userAuthInfo().get().consoleUser().get();
@@ -60,15 +70,34 @@ public abstract class ConsoleApiAction implements Runnable {
}
}
if (consoleApiParams.request().getMethod().equals(GET.toString())) {
getHandler(user);
} else {
if (verifyXSRF()) {
postHandler(user);
try {
if (consoleApiParams.request().getMethod().equals(GET.toString())) {
getHandler(user);
} else {
if (verifyXSRF()) {
postHandler(user);
}
}
} catch (ConsolePermissionForbiddenException e) {
logger.atWarning().withCause(e).log("Forbidden");
setFailedResponse("", SC_FORBIDDEN);
} catch (HttpException.BadRequestException | IllegalArgumentException e) {
logger.atWarning().withCause(e).log("Error in request");
setFailedResponse(Throwables.getRootCause(e).getMessage(), SC_BAD_REQUEST);
} catch (Throwable t) {
logger.atWarning().withCause(t).log("Internal server error");
setFailedResponse(Throwables.getRootCause(t).getMessage(), SC_INTERNAL_SERVER_ERROR);
}
}
protected void checkPermission(User user, String registrarId, ConsolePermission permission) {
if (!user.getUserRoles().hasPermission(registrarId, permission)) {
throw new ConsolePermissionForbiddenException(
String.format(
"User %s does not have permission %s on registrar %s",
user.getEmailAddress(), permission, registrarId));
}
}
protected void postHandler(User user) {
throw new UnsupportedOperationException("Console API POST handler not implemented");
@@ -90,10 +119,16 @@ public abstract class ConsoleApiAction implements Runnable {
.findFirst();
if (maybeCookie.isEmpty()
|| !consoleApiParams.xsrfTokenManager().validateToken(maybeCookie.get().getValue())) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
consoleApiParams.response().setStatus(SC_UNAUTHORIZED);
return false;
}
return true;
}
/** Specialized exception class used for failure when a user doesn't have the right permission. */
private static class ConsolePermissionForbiddenException extends RuntimeException {
private ConsolePermissionForbiddenException(String message) {
super(message);
}
}
}
@@ -15,8 +15,9 @@
package google.registry.ui.server.console;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import com.google.api.client.http.HttpStatusCodes;
import com.google.gson.Gson;
import google.registry.model.EppResourceUtils;
import google.registry.model.console.ConsolePermission;
@@ -59,16 +60,16 @@ public class ConsoleDomainGetAction extends ConsoleApiAction {
EppResourceUtils.loadByForeignKeyCached(
Domain.class, paramDomain, tm().getTransactionTime()));
if (possibleDomain.isEmpty()) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_NOT_FOUND);
consoleApiParams.response().setStatus(SC_NOT_FOUND);
return;
}
Domain domain = possibleDomain.get();
if (!user.getUserRoles()
.hasPermission(domain.getCurrentSponsorRegistrarId(), ConsolePermission.DOWNLOAD_DOMAINS)) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_NOT_FOUND);
consoleApiParams.response().setStatus(SC_NOT_FOUND);
return;
}
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
consoleApiParams.response().setStatus(SC_OK);
consoleApiParams.response().setPayload(gson.toJson(domain));
}
}
@@ -14,10 +14,11 @@
package google.registry.ui.server.console;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.console.ConsolePermission.DOWNLOAD_DOMAINS;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Ascii;
import com.google.gson.Gson;
@@ -82,22 +83,11 @@ public class ConsoleDomainListAction extends ConsoleApiAction {
@Override
protected void getHandler(User user) {
if (!user.getUserRoles().hasPermission(registrarId, DOWNLOAD_DOMAINS)) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
return;
}
if (resultsPerPage < 1 || resultsPerPage > 500) {
setFailedResponse(
"Results per page must be between 1 and 500 inclusive",
HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
return;
}
if (pageNumber < 0) {
setFailedResponse(
"Page number must be non-negative", HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
return;
}
checkPermission(user, registrarId, DOWNLOAD_DOMAINS);
checkArgument(
resultsPerPage > 0 && resultsPerPage <= 500,
"Results per page must be between 1 and 500 inclusive");
checkArgument(pageNumber >= 0, "Page number must be non-negative");
tm().transact(this::runInTransaction);
}
@@ -128,7 +118,7 @@ public class ConsoleDomainListAction extends ConsoleApiAction {
consoleApiParams
.response()
.setPayload(gson.toJson(new DomainListResult(domains, checkpoint, actualTotalResults)));
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
consoleApiParams.response().setStatus(SC_OK);
}
/** Creates the query to get the total number of matching domains, interpolating as necessary. */
@@ -58,7 +58,7 @@ public class ConsoleDumDownloadAction extends ConsoleApiAction {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public static final String PATH = "/console-api/dum-download";
private Clock clock;
private final Clock clock;
private final String registrarId;
private final String dumFileName;
@@ -76,11 +76,7 @@ public class ConsoleDumDownloadAction extends ConsoleApiAction {
@Override
protected void getHandler(User user) {
if (!user.getUserRoles().hasPermission(registrarId, ConsolePermission.DOWNLOAD_DOMAINS)) {
consoleApiParams.response().setStatus(HttpServletResponse.SC_FORBIDDEN);
return;
}
checkPermission(user, registrarId, ConsolePermission.DOWNLOAD_DOMAINS);
consoleApiParams.response().setContentType(MediaType.CSV_UTF_8);
consoleApiParams
.response()
@@ -14,20 +14,22 @@
package google.registry.ui.server.console;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.request.RequestParameters.extractRequiredParameter;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.base.Throwables;
import com.google.common.flogger.FluentLogger;
import com.google.common.base.Strings;
import com.google.gson.annotations.Expose;
import google.registry.flows.EppException.AuthenticationErrorException;
import google.registry.flows.PasswordOnlyTransportCredentials;
import google.registry.groups.GmailClient;
import google.registry.model.console.User;
import google.registry.model.registrar.Registrar;
import google.registry.request.Action;
import google.registry.request.HttpException.BadRequestException;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException;
@@ -43,9 +45,6 @@ import javax.mail.internet.InternetAddress;
method = {POST},
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
public class ConsoleEppPasswordAction extends ConsoleApiAction {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
protected static final String EMAIL_SUBJ = "EPP password update confirmation";
protected static final String EMAIL_BODY =
"Dear %s,\n" + "This is to confirm that your account password has been changed.";
@@ -57,70 +56,71 @@ public class ConsoleEppPasswordAction extends ConsoleApiAction {
private final AuthenticatedRegistrarAccessor registrarAccessor;
private final GmailClient gmailClient;
private final Optional<EppPasswordData> eppPasswordChangeRequest;
@Inject
public ConsoleEppPasswordAction(
ConsoleApiParams consoleApiParams,
AuthenticatedRegistrarAccessor registrarAccessor,
GmailClient gmailClient) {
GmailClient gmailClient,
@Parameter("eppPasswordChangeRequest") Optional<EppPasswordData> eppPasswordChangeRequest) {
super(consoleApiParams);
this.registrarAccessor = registrarAccessor;
this.gmailClient = gmailClient;
this.eppPasswordChangeRequest = eppPasswordChangeRequest;
}
private void confirmParamsAvailable() {
checkArgument(this.eppPasswordChangeRequest.isPresent(), "Epp Password update body is invalid");
var eppRequestBody = this.eppPasswordChangeRequest.get();
var errorMsg = "Missing param(s): %s";
checkArgument(!Strings.isNullOrEmpty(eppRequestBody.registrarId()), errorMsg, "registrarId");
checkArgument(!Strings.isNullOrEmpty(eppRequestBody.oldPassword()), errorMsg, "oldPassword");
checkArgument(!Strings.isNullOrEmpty(eppRequestBody.newPassword()), errorMsg, "newPassword");
checkArgument(
!Strings.isNullOrEmpty(eppRequestBody.newPasswordRepeat()), errorMsg, "newPasswordRepeat");
}
@Override
protected void postHandler(User user) {
String registrarId;
String oldPassword;
String newPassword;
String newPasswordRepeat;
this.confirmParamsAvailable();
try {
registrarId = extractRequiredParameter(consoleApiParams.request(), "registrarId");
oldPassword = extractRequiredParameter(consoleApiParams.request(), "oldPassword");
newPassword = extractRequiredParameter(consoleApiParams.request(), "newPassword");
newPasswordRepeat = extractRequiredParameter(consoleApiParams.request(), "newPasswordRepeat");
} catch (BadRequestException e) {
setFailedResponse(e.getMessage(), HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
return;
}
if (!newPassword.equals(newPasswordRepeat)) {
setFailedResponse("New password fields don't match", HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
return;
}
var eppRequestBody = this.eppPasswordChangeRequest.get();
checkArgument(
eppRequestBody.newPassword().equals(eppRequestBody.newPasswordRepeat()),
"New password fields don't match");
Registrar registrar;
try {
registrar = registrarAccessor.getRegistrar(registrarId);
registrar = registrarAccessor.getRegistrar(eppRequestBody.registrarId());
} catch (RegistrarAccessDeniedException e) {
setFailedResponse(e.getMessage(), HttpStatusCodes.STATUS_CODE_NOT_FOUND);
setFailedResponse(e.getMessage(), SC_NOT_FOUND);
return;
}
try {
credentials.validate(registrar, oldPassword);
credentials.validate(registrar, eppRequestBody.oldPassword());
} catch (AuthenticationErrorException e) {
setFailedResponse(e.getMessage(), HttpStatusCodes.STATUS_CODE_FORBIDDEN);
setFailedResponse(e.getMessage(), SC_FORBIDDEN);
return;
}
try {
tm().transact(
() -> {
tm().put(registrar.asBuilder().setPassword(newPassword).build());
this.gmailClient.sendEmail(
EmailMessage.create(
EMAIL_SUBJ,
String.format(EMAIL_BODY, registrar.getRegistrarName()),
new InternetAddress(registrar.getEmailAddress(), true)));
});
} catch (Throwable e) {
logger.atWarning().withCause(e).log("Failed to update password.");
String message =
Optional.ofNullable(Throwables.getRootCause(e).getMessage()).orElse("Unspecified error");
setFailedResponse(message, HttpStatusCodes.STATUS_CODE_SERVER_ERROR);
}
tm().transact(
() -> {
tm().put(registrar.asBuilder().setPassword(eppRequestBody.newPassword()).build());
this.gmailClient.sendEmail(
EmailMessage.create(
EMAIL_SUBJ,
String.format(EMAIL_BODY, registrar.getRegistrarName()),
new InternetAddress(registrar.getEmailAddress(), true)));
});
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
consoleApiParams.response().setStatus(SC_OK);
}
public record EppPasswordData(
@Expose String registrarId,
@Expose String oldPassword,
@Expose String newPassword,
@Expose String newPasswordRepeat) {}
}
@@ -14,6 +14,7 @@
package google.registry.ui.server.console;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.GET;
@@ -23,10 +24,10 @@ import static google.registry.request.RequestParameters.extractOptionalLongParam
import static google.registry.request.RequestParameters.extractOptionalParameter;
import static google.registry.request.RequestParameters.extractRequiredParameter;
import static google.registry.ui.server.registrar.RegistryLockPostAction.VERIFICATION_EMAIL_TEMPLATE;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gson.Gson;
import google.registry.flows.EppException;
import google.registry.flows.domain.DomainFlowUtils;
@@ -37,7 +38,6 @@ import google.registry.model.domain.RegistryLock;
import google.registry.model.registrar.Registrar;
import google.registry.model.tld.RegistryLockDao;
import google.registry.request.Action;
import google.registry.request.HttpException;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
@@ -66,8 +66,6 @@ import org.joda.time.Duration;
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
public class ConsoleRegistryLockAction extends ConsoleApiAction {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
static final String PATH = "/console-api/registry-lock";
private final DomainLockUtils domainLockUtils;
@@ -91,12 +89,9 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
@Override
protected void getHandler(User user) {
if (!user.getUserRoles().hasPermission(registrarId, ConsolePermission.REGISTRY_LOCK)) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
return;
}
checkPermission(user, registrarId, ConsolePermission.REGISTRY_LOCK);
consoleApiParams.response().setPayload(gson.toJson(getLockedDomains()));
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
consoleApiParams.response().setStatus(SC_OK);
}
@Override
@@ -104,85 +99,55 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
HttpServletRequest req = consoleApiParams.request();
Response response = consoleApiParams.response();
// User must have the proper permission on the registrar
if (!user.getUserRoles().hasPermission(registrarId, ConsolePermission.REGISTRY_LOCK)) {
setFailedResponse("", HttpStatusCodes.STATUS_CODE_FORBIDDEN);
return;
}
checkPermission(user, registrarId, ConsolePermission.REGISTRY_LOCK);
// Shouldn't happen, but double-check the registrar has registry lock enabled
Registrar registrar = Registrar.loadByRegistrarIdCached(registrarId).get();
if (!registrar.isRegistryLockAllowed()) {
setFailedResponse(
String.format("Registry lock not allowed for registrar %s", registrarId),
HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
return;
}
checkArgument(
registrar.isRegistryLockAllowed(),
"Registry lock not allowed for registrar %s",
registrarId);
// Retrieve and validate the necessary params
String domainName;
boolean isLock;
Optional<String> maybePassword;
Optional<Long> relockDurationMillis;
String domainName = extractRequiredParameter(req, "domainName");
boolean isLock = extractBooleanParameter(req, "isLock");
Optional<String> maybePassword = extractOptionalParameter(req, "password");
Optional<Long> relockDurationMillis = extractOptionalLongParameter(req, "relockDurationMillis");
try {
domainName = extractRequiredParameter(req, "domainName");
isLock = extractBooleanParameter(req, "isLock");
maybePassword = extractOptionalParameter(req, "password");
relockDurationMillis = extractOptionalLongParameter(req, "relockDurationMillis");
DomainFlowUtils.validateDomainName(domainName);
} catch (HttpException.BadRequestException | EppException e) {
logger.atWarning().withCause(e).log("Bad request when attempting registry lock/unlock");
setFailedResponse(e.getMessage(), HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
return;
} catch (EppException e) {
throw new IllegalArgumentException(e);
}
// Passwords aren't required for admin users, otherwise we need to validate it
boolean isAdmin = user.getUserRoles().isAdmin();
if (!isAdmin) {
if (maybePassword.isEmpty()) {
setFailedResponse("No password provided", HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
return;
}
checkArgument(maybePassword.isPresent(), "No password provided");
if (!user.verifyRegistryLockPassword(maybePassword.get())) {
setFailedResponse(
"Incorrect registry lock password", HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
setFailedResponse("Incorrect registry lock password", SC_UNAUTHORIZED);
return;
}
}
Optional<String> maybeRegistryLockEmail = user.getRegistryLockEmailAddress();
if (maybeRegistryLockEmail.isEmpty()) {
setFailedResponse(
"User has no registry lock email address", HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
return;
}
String registryLockEmail = maybeRegistryLockEmail.get();
try {
tm().transact(
() -> {
RegistryLock registryLock =
isLock
? domainLockUtils.saveNewRegistryLockRequest(
domainName, registrarId, registryLockEmail, isAdmin)
: domainLockUtils.saveNewRegistryUnlockRequest(
domainName,
registrarId,
isAdmin,
relockDurationMillis.map(Duration::new));
sendVerificationEmail(registryLock, registryLockEmail, isLock);
});
} catch (IllegalArgumentException e) {
// Catch IllegalArgumentExceptions separately to give a nicer error message and code
logger.atWarning().withCause(e).log("Failed to lock/unlock domain");
setFailedResponse(e.getMessage(), HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
return;
} catch (Throwable t) {
logger.atWarning().withCause(t).log("Failed to lock/unlock domain");
setFailedResponse("Internal server error", HttpStatusCodes.STATUS_CODE_SERVER_ERROR);
return;
}
response.setStatus(HttpStatusCodes.STATUS_CODE_OK);
String registryLockEmail =
user.getRegistryLockEmailAddress()
.orElseThrow(
() -> new IllegalArgumentException("User has no registry lock email address"));
tm().transact(
() -> {
RegistryLock registryLock =
isLock
? domainLockUtils.saveNewRegistryLockRequest(
domainName, registrarId, registryLockEmail, isAdmin)
: domainLockUtils.saveNewRegistryUnlockRequest(
domainName,
registrarId,
isAdmin,
relockDurationMillis.map(Duration::new));
sendVerificationEmail(registryLock, registryLockEmail, isLock);
});
response.setStatus(SC_OK);
}
private void sendVerificationEmail(RegistryLock lock, String userEmail, boolean isLock) {
@@ -15,8 +15,8 @@
package google.registry.ui.server.console;
import static google.registry.request.Action.Method.GET;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableMap;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.console.User;
@@ -88,6 +88,6 @@ public class ConsoleUserDataAction extends ConsoleApiAction {
"technicalDocsUrl", technicalDocsUrl));
consoleApiParams.response().setPayload(json.toString());
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
consoleApiParams.response().setStatus(SC_OK);
}
}
@@ -19,14 +19,16 @@ import static com.google.common.base.Strings.isNullOrEmpty;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import com.google.gson.Gson;
import google.registry.model.console.ConsolePermission;
import google.registry.model.console.User;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.RegistrarBase;
import google.registry.model.registrar.RegistrarBase.State;
import google.registry.model.registrar.RegistrarPoc;
import google.registry.request.Action;
@@ -46,11 +48,13 @@ import javax.inject.Named;
public class RegistrarsAction extends ConsoleApiAction {
private static final int PASSWORD_LENGTH = 16;
private static final int PASSCODE_LENGTH = 5;
private static final ImmutableList<RegistrarBase.Type> allowedRegistrarTypes =
ImmutableList.of(Registrar.Type.REAL, RegistrarBase.Type.OTE);
static final String PATH = "/console-api/registrars";
private final Gson gson;
private Optional<Registrar> registrar;
private StringGenerator passwordGenerator;
private StringGenerator passcodeGenerator;
private final Optional<Registrar> registrar;
private final StringGenerator passwordGenerator;
private final StringGenerator passcodeGenerator;
@Inject
public RegistrarsAction(
@@ -69,92 +73,82 @@ public class RegistrarsAction extends ConsoleApiAction {
@Override
protected void getHandler(User user) {
if (!user.getUserRoles().hasGlobalPermission(ConsolePermission.VIEW_REGISTRARS)) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
consoleApiParams.response().setStatus(SC_FORBIDDEN);
return;
}
ImmutableList<Registrar> registrars =
Streams.stream(Registrar.loadAll())
.filter(r -> r.getType() == Registrar.Type.REAL)
.filter(r -> allowedRegistrarTypes.contains(r.getType()))
.collect(ImmutableList.toImmutableList());
consoleApiParams.response().setPayload(gson.toJson(registrars));
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
consoleApiParams.response().setStatus(SC_OK);
}
@Override
protected void postHandler(User user) {
if (!user.getUserRoles().isAdmin()) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
consoleApiParams.response().setStatus(SC_FORBIDDEN);
return;
}
if (registrar.isEmpty()) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
consoleApiParams.response().setPayload(gson.toJson("'registrar' parameter is not present"));
return;
}
Registrar registrarParam = registrar.get();
Registrar registrarParam =
registrar.orElseThrow(
() -> new IllegalArgumentException("'registrar' parameter is not present"));
String errorMsg = "Missing value for %s";
try {
checkArgument(!isNullOrEmpty(registrarParam.getRegistrarId()), errorMsg, "registrarId");
checkArgument(!isNullOrEmpty(registrarParam.getRegistrarName()), errorMsg, "name");
checkArgument(!registrarParam.getBillingAccountMap().isEmpty(), errorMsg, "billingAccount");
checkArgument(registrarParam.getIanaIdentifier() != null, String.format(errorMsg, "ianaId"));
checkArgument(
!isNullOrEmpty(registrarParam.getIcannReferralEmail()), errorMsg, "referralEmail");
checkArgument(!isNullOrEmpty(registrarParam.getDriveFolderId()), errorMsg, "driveId");
checkArgument(!isNullOrEmpty(registrarParam.getEmailAddress()), errorMsg, "consoleUserEmail");
checkArgument(
registrarParam.getLocalizedAddress() != null
&& !isNullOrEmpty(registrarParam.getLocalizedAddress().getState())
&& !isNullOrEmpty(registrarParam.getLocalizedAddress().getCity())
&& !isNullOrEmpty(registrarParam.getLocalizedAddress().getZip())
&& !isNullOrEmpty(registrarParam.getLocalizedAddress().getCountryCode())
&& !registrarParam.getLocalizedAddress().getStreet().isEmpty(),
errorMsg,
"address");
checkArgument(!isNullOrEmpty(registrarParam.getRegistrarId()), errorMsg, "registrarId");
checkArgument(!isNullOrEmpty(registrarParam.getRegistrarName()), errorMsg, "name");
checkArgument(!registrarParam.getBillingAccountMap().isEmpty(), errorMsg, "billingAccount");
checkArgument(registrarParam.getIanaIdentifier() != null, String.format(errorMsg, "ianaId"));
checkArgument(
!isNullOrEmpty(registrarParam.getIcannReferralEmail()), errorMsg, "referralEmail");
checkArgument(!isNullOrEmpty(registrarParam.getDriveFolderId()), errorMsg, "driveId");
checkArgument(!isNullOrEmpty(registrarParam.getEmailAddress()), errorMsg, "consoleUserEmail");
checkArgument(
registrarParam.getLocalizedAddress() != null
&& !isNullOrEmpty(registrarParam.getLocalizedAddress().getState())
&& !isNullOrEmpty(registrarParam.getLocalizedAddress().getCity())
&& !isNullOrEmpty(registrarParam.getLocalizedAddress().getZip())
&& !isNullOrEmpty(registrarParam.getLocalizedAddress().getCountryCode())
&& !registrarParam.getLocalizedAddress().getStreet().isEmpty(),
errorMsg,
"address");
String password = passwordGenerator.createString(PASSWORD_LENGTH);
String phonePasscode = passcodeGenerator.createString(PASSCODE_LENGTH);
String password = passwordGenerator.createString(PASSWORD_LENGTH);
String phonePasscode = passcodeGenerator.createString(PASSCODE_LENGTH);
Registrar registrar =
new Registrar.Builder()
.setRegistrarId(registrarParam.getRegistrarId())
.setRegistrarName(registrarParam.getRegistrarName())
.setBillingAccountMap(registrarParam.getBillingAccountMap())
.setIanaIdentifier(Long.valueOf(registrarParam.getIanaIdentifier()))
.setIcannReferralEmail(registrarParam.getIcannReferralEmail())
.setEmailAddress(registrarParam.getIcannReferralEmail())
.setDriveFolderId(registrarParam.getDriveFolderId())
.setType(Registrar.Type.REAL)
.setPassword(password)
.setPhonePasscode(phonePasscode)
.setState(State.PENDING)
.setLocalizedAddress(registrarParam.getLocalizedAddress())
.build();
Registrar registrar =
new Registrar.Builder()
.setRegistrarId(registrarParam.getRegistrarId())
.setRegistrarName(registrarParam.getRegistrarName())
.setBillingAccountMap(registrarParam.getBillingAccountMap())
.setIanaIdentifier(registrarParam.getIanaIdentifier())
.setIcannReferralEmail(registrarParam.getIcannReferralEmail())
.setEmailAddress(registrarParam.getIcannReferralEmail())
.setDriveFolderId(registrarParam.getDriveFolderId())
.setType(Registrar.Type.REAL)
.setPassword(password)
.setPhonePasscode(phonePasscode)
.setState(State.PENDING)
.setLocalizedAddress(registrarParam.getLocalizedAddress())
.build();
RegistrarPoc contact =
new RegistrarPoc.Builder()
.setRegistrar(registrar)
.setName(registrarParam.getEmailAddress())
.setEmailAddress(registrarParam.getEmailAddress())
.setLoginEmailAddress(registrarParam.getEmailAddress())
.build();
RegistrarPoc contact =
new RegistrarPoc.Builder()
.setRegistrar(registrar)
.setName(registrarParam.getEmailAddress())
.setEmailAddress(registrarParam.getEmailAddress())
.setLoginEmailAddress(registrarParam.getEmailAddress())
.build();
tm().transact(
() -> {
checkArgument(
Registrar.loadByRegistrarId(registrar.getRegistrarId()).isEmpty(),
"Registrar with registrarId %s already exists",
registrar.getRegistrarId());
tm().putAll(registrar, contact);
});
} catch (IllegalArgumentException e) {
setFailedResponse(e.getMessage(), HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
} catch (Throwable e) {
setFailedResponse(e.getMessage(), HttpStatusCodes.STATUS_CODE_SERVER_ERROR);
}
tm().transact(
() -> {
checkArgument(
Registrar.loadByRegistrarId(registrar.getRegistrarId()).isEmpty(),
"Registrar with registrarId %s already exists",
registrar.getRegistrarId());
tm().putAll(registrar, contact);
});
}
}
@@ -14,12 +14,13 @@
package google.registry.ui.server.console.settings;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
@@ -66,11 +67,7 @@ public class ContactAction extends ConsoleApiAction {
@Override
protected void getHandler(User user) {
if (!user.getUserRoles().hasPermission(registrarId, ConsolePermission.VIEW_REGISTRAR_DETAILS)) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
return;
}
checkPermission(user, registrarId, ConsolePermission.VIEW_REGISTRAR_DETAILS);
ImmutableList<RegistrarPoc> am =
tm().transact(
() ->
@@ -81,23 +78,14 @@ public class ContactAction extends ConsoleApiAction {
.filter(r -> !r.getTypes().isEmpty())
.collect(toImmutableList()));
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
consoleApiParams.response().setStatus(SC_OK);
consoleApiParams.response().setPayload(gson.toJson(am));
}
@Override
protected void postHandler(User user) {
if (!user.getUserRoles().hasPermission(registrarId, ConsolePermission.EDIT_REGISTRAR_DETAILS)) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
return;
}
if (contacts.isEmpty()) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
consoleApiParams.response().setPayload(gson.toJson("Contacts parameter is not present"));
return;
}
checkPermission(user, registrarId, ConsolePermission.EDIT_REGISTRAR_DETAILS);
checkArgument(contacts.isPresent(), "Contacts parameter is not present");
Registrar registrar =
Registrar.loadByRegistrarId(registrarId)
.orElseThrow(
@@ -120,12 +108,10 @@ public class ContactAction extends ConsoleApiAction {
} catch (FormException e) {
logger.atWarning().withCause(e).log(
"Error processing contacts post request for registrar: %s", registrarId);
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
consoleApiParams.response().setPayload(e.getMessage());
return;
throw new IllegalArgumentException(e);
}
RegistrarPoc.updateContacts(registrar, updatedContacts);
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
consoleApiParams.response().setStatus(SC_OK);
}
}
@@ -14,10 +14,13 @@
package google.registry.ui.server.console.settings;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import com.google.api.client.http.HttpStatusCodes;
import google.registry.flows.certs.CertificateChecker;
import google.registry.flows.certs.CertificateChecker.InsecureCertificateException;
import google.registry.model.console.ConsolePermission;
@@ -62,22 +65,14 @@ public class SecurityAction extends ConsoleApiAction {
@Override
protected void postHandler(User user) {
if (!user.getUserRoles().hasPermission(registrarId, ConsolePermission.EDIT_REGISTRAR_DETAILS)) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
return;
}
if (registrar.isEmpty()) {
setFailedResponse(
"'registrar' parameter is not present", HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
return;
}
checkPermission(user, registrarId, ConsolePermission.EDIT_REGISTRAR_DETAILS);
checkArgument(registrar.isPresent(), "'registrar' parameter is not present");
Registrar savedRegistrar;
try {
savedRegistrar = registrarAccessor.getRegistrar(registrarId);
} catch (RegistrarAccessDeniedException e) {
setFailedResponse(e.getMessage(), HttpStatusCodes.STATUS_CODE_FORBIDDEN);
setFailedResponse(e.getMessage(), SC_FORBIDDEN);
return;
}
@@ -111,12 +106,11 @@ public class SecurityAction extends ConsoleApiAction {
}
}
} catch (InsecureCertificateException e) {
setFailedResponse(
"Invalid certificate in parameter", HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
setFailedResponse("Invalid certificate in parameter", SC_BAD_REQUEST);
return;
}
tm().put(updatedRegistrar.build());
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
consoleApiParams.response().setStatus(SC_OK);
}
}
@@ -14,10 +14,12 @@
package google.registry.ui.server.console.settings;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import com.google.api.client.http.HttpStatusCodes;
import google.registry.model.console.ConsolePermission;
import google.registry.model.console.User;
import google.registry.model.registrar.Registrar;
@@ -45,8 +47,8 @@ import javax.inject.Inject;
public class WhoisRegistrarFieldsAction extends ConsoleApiAction {
static final String PATH = "/console-api/settings/whois-fields";
private AuthenticatedRegistrarAccessor registrarAccessor;
private Optional<Registrar> registrar;
private final AuthenticatedRegistrarAccessor registrarAccessor;
private final Optional<Registrar> registrar;
@Inject
public WhoisRegistrarFieldsAction(
@@ -60,19 +62,9 @@ public class WhoisRegistrarFieldsAction extends ConsoleApiAction {
@Override
protected void postHandler(User user) {
if (registrar.isEmpty()) {
setFailedResponse(
"'registrar' parameter is not present", HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
return;
}
if (!user.getUserRoles()
.hasPermission(
registrar.get().getRegistrarId(), ConsolePermission.EDIT_REGISTRAR_DETAILS)) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
return;
}
checkArgument(registrar.isPresent(), "'registrar' parameter is not present");
checkPermission(
user, registrar.get().getRegistrarId(), ConsolePermission.EDIT_REGISTRAR_DETAILS);
tm().transact(() -> loadAndModifyRegistrar(registrar.get()));
}
@@ -82,8 +74,7 @@ public class WhoisRegistrarFieldsAction extends ConsoleApiAction {
// reload to make sure the object has all the correct fields
savedRegistrar = registrarAccessor.getRegistrar(providedRegistrar.getRegistrarId());
} catch (RegistrarAccessDeniedException e) {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
consoleApiParams.response().setPayload(e.getMessage());
setFailedResponse(e.getMessage(), SC_FORBIDDEN);
return;
}
@@ -91,7 +82,9 @@ public class WhoisRegistrarFieldsAction extends ConsoleApiAction {
newRegistrar.setWhoisServer(providedRegistrar.getWhoisServer());
newRegistrar.setUrl(providedRegistrar.getUrl());
newRegistrar.setLocalizedAddress(providedRegistrar.getLocalizedAddress());
newRegistrar.setPhoneNumber(providedRegistrar.getPhoneNumber());
newRegistrar.setFaxNumber(providedRegistrar.getFaxNumber());
tm().put(newRegistrar.build());
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
consoleApiParams.response().setStatus(SC_OK);
}
}
@@ -32,6 +32,7 @@ import google.registry.request.RequestScope;
import google.registry.request.Response;
import google.registry.request.auth.AuthResult;
import google.registry.security.XsrfTokenManager;
import google.registry.ui.server.console.ConsoleEppPasswordAction.EppPasswordData;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Optional;
import org.joda.time.DateTime;
@@ -232,4 +233,11 @@ public final class RegistrarConsoleModule {
public static Optional<String> provideSearchTerm(HttpServletRequest req) {
return extractOptionalParameter(req, "searchTerm");
}
@Provides
@Parameter("eppPasswordChangeRequest")
public static Optional<EppPasswordData> provideEppPasswordChangeRequest(
Gson gson, @OptionalJsonPayload Optional<JsonElement> payload) {
return payload.map(s -> gson.fromJson(s, EppPasswordData.class));
}
}
@@ -14,9 +14,6 @@
package google.registry.rde;
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_BAD_REQUEST;
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_OK;
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_UNAUTHORIZED;
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.common.Cursor.CursorType.RDE_REPORT;
@@ -26,6 +23,9 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.loadByKey;
import static google.registry.testing.DatabaseHelper.persistResource;
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import static org.joda.time.Duration.standardDays;
import static org.joda.time.Duration.standardSeconds;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -121,7 +121,7 @@ public class RdeReportActionTest {
gcsUtils.createFromBytes(reportFile, Ghostryde.encode(REPORT_XML.read(), encryptKey));
tm().transact(() -> RdeRevision.saveRevision("test", DateTime.parse("2006-06-06TZ"), FULL, 0));
when(httpUrlConnection.getOutputStream()).thenReturn(connectionOutputStream);
when(httpUrlConnection.getResponseCode()).thenReturn(STATUS_CODE_OK);
when(httpUrlConnection.getResponseCode()).thenReturn(SC_OK);
when(httpUrlConnection.getInputStream()).thenReturn(IIRDEA_GOOD_XML.openBufferedStream());
}
@@ -263,7 +263,7 @@ public class RdeReportActionTest {
@Test
void testRunWithLock_badRequest_throws500WithErrorInfo() throws Exception {
when(httpUrlConnection.getResponseCode()).thenReturn(STATUS_CODE_BAD_REQUEST);
when(httpUrlConnection.getResponseCode()).thenReturn(SC_BAD_REQUEST);
when(httpUrlConnection.getErrorStream()).thenReturn(IIRDEA_BAD_XML.openBufferedStream());
InternalServerErrorException thrown =
assertThrows(
@@ -274,7 +274,7 @@ public class RdeReportActionTest {
@Test
void testRunWithLock_notAuthorized() throws Exception {
when(httpUrlConnection.getResponseCode()).thenReturn(STATUS_CODE_UNAUTHORIZED);
when(httpUrlConnection.getResponseCode()).thenReturn(SC_UNAUTHORIZED);
UrlConnectionException thrown =
assertThrows(
UrlConnectionException.class, () -> createAction().runWithLock(loadRdeReportCursor()));
@@ -14,11 +14,11 @@
package google.registry.reporting.icann;
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_BAD_REQUEST;
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_OK;
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_SERVER_ERROR;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.DatabaseHelper.createTld;
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
@@ -61,7 +61,7 @@ class IcannHttpReporterTest {
createTld("test");
createTld("xn--abc123");
when(connection.getOutputStream()).thenReturn(outputStream);
when(connection.getResponseCode()).thenReturn(STATUS_CODE_OK);
when(connection.getResponseCode()).thenReturn(SC_OK);
when(connection.getInputStream()).thenReturn(IIRDEA_GOOD_XML.openBufferedStream());
reporter.urlConnectionService = urlConnectionService;
reporter.password = "fakePass";
@@ -99,7 +99,7 @@ class IcannHttpReporterTest {
@Test
void testFail_BadIirdeaResponse() throws Exception {
when(connection.getResponseCode()).thenReturn(STATUS_CODE_BAD_REQUEST);
when(connection.getResponseCode()).thenReturn(SC_BAD_REQUEST);
when(connection.getErrorStream()).thenReturn(IIRDEA_BAD_XML.openBufferedStream());
assertThat(reporter.send(FAKE_PAYLOAD, "test-transactions-201706.csv")).isFalse();
verify(connection).getErrorStream();
@@ -107,7 +107,7 @@ class IcannHttpReporterTest {
@Test
void testFail_OtherBadHttpResponse() throws Exception {
when(connection.getResponseCode()).thenReturn(STATUS_CODE_SERVER_ERROR);
when(connection.getResponseCode()).thenReturn(SC_INTERNAL_SERVER_ERROR);
assertThat(reporter.send(FAKE_PAYLOAD, "test-transactions-201706.csv")).isFalse();
verify(connection, times(0)).getInputStream();
}
@@ -53,7 +53,7 @@ public final class RegistryTestServerMain {
names = "--address",
description = "Listening address.",
validateWith = HostAndPortParameter.class)
private HostAndPort address = HostAndPort.fromString("[::]:8080");
private HostAndPort address = HostAndPort.fromString("[::1]:8080");
@Parameter(names = "--fixtures", description = "Fixtures to load into the DB.")
private List<Fixture> fixtures = ImmutableList.of(Fixture.BASIC);
@@ -16,10 +16,12 @@ package google.registry.ui.server.console;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.DatabaseHelper.createTld;
import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import google.registry.model.console.RegistrarRole;
@@ -68,8 +70,7 @@ public class ConsoleDomainGetActionTest {
.build()))),
"exists.tld");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
.isEqualTo(
"{\"domainName\":\"exists.tld\",\"adminContact\":{\"key\":\"3-ROID\",\"kind\":"
@@ -88,8 +89,7 @@ public class ConsoleDomainGetActionTest {
void testFailure_emptyAuth() {
ConsoleDomainGetAction action = createAction(AuthResult.NOT_AUTHENTICATED, "exists.tld");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_UNAUTHORIZED);
}
@Test
@@ -97,8 +97,7 @@ public class ConsoleDomainGetActionTest {
ConsoleDomainGetAction action =
createAction(AuthResult.createApp("service@registry.example"), "exists.tld");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_UNAUTHORIZED);
}
@Test
@@ -109,8 +108,7 @@ public class ConsoleDomainGetActionTest {
UserAuthInfo.create(mock(com.google.appengine.api.users.User.class), false)),
"exists.tld");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_UNAUTHORIZED);
}
@Test
@@ -120,8 +118,7 @@ public class ConsoleDomainGetActionTest {
AuthResult.createUser(UserAuthInfo.create(createUser(new UserRoles.Builder().build()))),
"exists.tld");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_NOT_FOUND);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_NOT_FOUND);
}
@Test
@@ -132,8 +129,7 @@ public class ConsoleDomainGetActionTest {
UserAuthInfo.create(createUser(new UserRoles.Builder().setIsAdmin(true).build()))),
"nonexistent.tld");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_NOT_FOUND);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_NOT_FOUND);
}
private User createUser(UserRoles userRoles) {
@@ -20,9 +20,9 @@ import static google.registry.testing.DatabaseHelper.createAdminUser;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
import static google.registry.testing.DatabaseHelper.persistDomainAsDeleted;
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static org.mockito.Mockito.when;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.Iterables;
import com.google.gson.Gson;
import google.registry.model.EppResourceUtils;
@@ -230,15 +230,13 @@ public class ConsoleDomainListActionTest {
void testFailure_invalidResultsPerPage() {
ConsoleDomainListAction action = createAction("TheRegistrar", null, 0, 0, null, null);
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
.isEqualTo("Results per page must be between 1 and 500 inclusive");
action = createAction("TheRegistrar", null, 0, 501, null, null);
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
.isEqualTo("Results per page must be between 1 and 500 inclusive");
}
@@ -247,8 +245,7 @@ public class ConsoleDomainListActionTest {
void testFailure_invalidPageNumber() {
ConsoleDomainListAction action = createAction("TheRegistrar", null, -1, 10, null, null);
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
.isEqualTo("Page number must be non-negative");
}
@@ -16,9 +16,10 @@ package google.registry.ui.server.console;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.DatabaseHelper.createTld;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static org.mockito.Mockito.when;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableList;
import com.google.gson.Gson;
import google.registry.model.console.GlobalRole;
@@ -82,7 +83,7 @@ class ConsoleDumDownloadActionTest {
"1exists.tld,2024-04-15 00:00:00.001+00,2025-02-09 00:00:00.001+00,{INACTIVE}",
"0exists.tld,2024-04-15 00:00:00+00,2025-02-09 00:00:00+00,{INACTIVE}");
FakeResponse response = (FakeResponse) consoleApiParams.response();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(response.getStatus()).isEqualTo(SC_OK);
ImmutableList<String> actual =
ImmutableList.copyOf(response.getStringWriter().toString().split("\r\n"));
assertThat(actual).containsExactlyElementsIn(expected);
@@ -99,8 +100,7 @@ class ConsoleDumDownloadActionTest {
AuthResult authResult = AuthResult.createUser(UserAuthInfo.create(user));
ConsoleDumDownloadAction action = createAction(Optional.of(authResult));
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_FORBIDDEN);
}
private ConsoleDumDownloadAction createAction(Optional<AuthResult> maybeAuthResult) {
@@ -19,14 +19,16 @@ import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.O
import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.persistNewRegistrar;
import static google.registry.testing.DatabaseHelper.persistResource;
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.gson.Gson;
import google.registry.flows.PasswordOnlyTransportCredentials;
@@ -37,14 +39,20 @@ import google.registry.model.console.UserRoles;
import google.registry.model.registrar.Registrar;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.request.Action;
import google.registry.request.RequestModule;
import google.registry.request.auth.AuthResult;
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
import google.registry.request.auth.UserAuthInfo;
import google.registry.testing.FakeConsoleApiParams;
import google.registry.testing.FakeResponse;
import google.registry.tools.GsonUtils;
import google.registry.ui.server.console.ConsoleEppPasswordAction.EppPasswordData;
import google.registry.ui.server.registrar.ConsoleApiParams;
import google.registry.ui.server.registrar.RegistrarConsoleModule;
import google.registry.util.EmailMessage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Optional;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
@@ -54,6 +62,9 @@ import org.junit.jupiter.api.extension.RegisterExtension;
class ConsoleEppPasswordActionTest {
private static final Gson GSON = GsonUtils.provideGson();
private static String eppPostData =
"{\"registrarId\":\"%s\",\"oldPassword\":\"%s\",\"newPassword\":\"%s\",\"newPasswordRepeat\":\"%s\"}";
private ConsoleApiParams consoleApiParams;
protected PasswordOnlyTransportCredentials credentials = new PasswordOnlyTransportCredentials();
private FakeResponse response;
@@ -78,68 +89,38 @@ class ConsoleEppPasswordActionTest {
}
@Test
void testFailure_emptyParams() {
ConsoleEppPasswordAction action = createAction();
void testFailure_emptyParams() throws IOException {
ConsoleEppPasswordAction action = createAction("", "", "", "");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
.isEqualTo("Missing parameter: registrarId");
.isEqualTo("Missing param(s): registrarId");
}
@Test
void testFailure_passwordsDontMatch() {
ConsoleEppPasswordAction action = createAction();
setParams(
ImmutableMap.of(
"registrarId",
"registrarId",
"oldPassword",
"oldPassword",
"newPassword",
"newPassword",
"newPasswordRepeat",
"newPasswordRepeat"));
void testFailure_passwordsDontMatch() throws IOException {
ConsoleEppPasswordAction action =
createAction("registrarId", "oldPassword", "newPassword", "newPasswordRepeat");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
.contains("New password fields don't match");
}
@Test
void testFailure_existingPasswordIncorrect() {
ConsoleEppPasswordAction action = createAction();
setParams(
ImmutableMap.of(
"registrarId",
"registrarId",
"oldPassword",
"oldPassword",
"newPassword",
"randomPasword",
"newPasswordRepeat",
"randomPasword"));
void testFailure_existingPasswordIncorrect() throws IOException {
ConsoleEppPasswordAction action =
createAction("registrarId", "oldPassword", "randomPasword", "randomPasword");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_FORBIDDEN);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
.contains("Registrar password is incorrect");
}
@Test
void testSuccess_sendsConfirmationEmail() throws AddressException {
ConsoleEppPasswordAction action = createAction();
setParams(
ImmutableMap.of(
"registrarId",
"registrarId",
"oldPassword",
"foobar",
"newPassword",
"randomPassword",
"newPasswordRepeat",
"randomPassword"));
void testSuccess_sendsConfirmationEmail() throws IOException, AddressException {
ConsoleEppPasswordAction action =
createAction("registrarId", "foobar", "randomPassword", "randomPassword");
action.run();
verify(gmailClient, times(1))
.sendEmail(
@@ -148,42 +129,24 @@ class ConsoleEppPasswordActionTest {
"Dear registrarId name,\n"
+ "This is to confirm that your account password has been changed.",
new InternetAddress("testEmail@google.com")));
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
}
@Test
void testSuccess_passwordUpdated() {
ConsoleEppPasswordAction action = createAction();
setParams(
ImmutableMap.of(
"registrarId",
"registrarId",
"oldPassword",
"foobar",
"newPassword",
"randomPassword",
"newPasswordRepeat",
"randomPassword"));
void testSuccess_passwordUpdated() throws IOException {
ConsoleEppPasswordAction action =
createAction("registrarId", "foobar", "randomPassword", "randomPassword");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
assertDoesNotThrow(
() -> {
credentials.validate(loadRegistrar("registrarId"), "randomPassword");
});
}
private void setParams(ImmutableMap<String, String> params) {
params.entrySet().stream()
.forEach(
entry -> {
when(consoleApiParams.request().getParameter(entry.getKey()))
.thenReturn(entry.getValue());
});
}
private ConsoleEppPasswordAction createAction() {
private ConsoleEppPasswordAction createAction(
String registrarId, String oldPassword, String newPassword, String newPasswordRepeat)
throws IOException {
response = new FakeResponse();
User user =
new User.Builder()
@@ -197,8 +160,18 @@ class ConsoleEppPasswordActionTest {
AuthenticatedRegistrarAccessor.createForTesting(
ImmutableSetMultimap.of("registrarId", OWNER));
when(consoleApiParams.request().getMethod()).thenReturn(Action.Method.POST.toString());
doReturn(
new BufferedReader(
new StringReader(
String.format(
eppPostData, registrarId, oldPassword, newPassword, newPasswordRepeat))))
.when(consoleApiParams.request())
.getReader();
Optional<EppPasswordData> maybePasswordChangeRequest =
RegistrarConsoleModule.provideEppPasswordChangeRequest(
GSON, RequestModule.provideJsonBody(consoleApiParams.request(), GSON));
return new ConsoleEppPasswordAction(
consoleApiParams, authenticatedRegistrarAccessor, gmailClient);
consoleApiParams, authenticatedRegistrarAccessor, gmailClient, maybePasswordChangeRequest);
}
}
@@ -24,11 +24,14 @@ import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.SqlHelper.getMostRecentRegistryLockByRepoId;
import static google.registry.testing.SqlHelper.saveRegistryLock;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import google.registry.groups.GmailClient;
@@ -130,7 +133,7 @@ public class ConsoleRegistryLockActionTest {
.setLockCompletionTime(fakeClock.nowUtc())
.build());
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(response.getPayload())
.isEqualTo(
"""
@@ -222,7 +225,7 @@ public class ConsoleRegistryLockActionTest {
saveRegistryLock(unlockedLock);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(response.getStatus()).isEqualTo(SC_OK);
// We should include all the locks that are currently locked, which does not include pending
// locks or completed unlocks
assertThat(response.getPayload())
@@ -252,7 +255,7 @@ public class ConsoleRegistryLockActionTest {
@Test
void testGet_noLocks() {
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(response.getPayload()).isEqualTo("[]");
}
@@ -265,7 +268,7 @@ public class ConsoleRegistryLockActionTest {
.build();
action = createGetAction();
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
}
@Test
@@ -282,14 +285,14 @@ public class ConsoleRegistryLockActionTest {
.build();
action = createGetAction();
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
}
@Test
void testPost_lock() throws Exception {
action = createDefaultPostAction(true);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(getMostRecentRegistryLockByRepoId(defaultDomain.getRepoId())).isPresent();
verifyEmail();
// Doesn't actually change the status values (hasn't been verified)
@@ -302,7 +305,7 @@ public class ConsoleRegistryLockActionTest {
persistResource(defaultDomain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
action = createDefaultPostAction(false);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(response.getStatus()).isEqualTo(SC_OK);
verifyEmail();
// Doesn't actually change the status values (hasn't been verified)
assertThat(loadByEntity(defaultDomain).getStatusValues())
@@ -320,7 +323,7 @@ public class ConsoleRegistryLockActionTest {
"registryLockPassword",
Optional.of(Duration.standardDays(1).getMillis()));
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(response.getStatus()).isEqualTo(SC_OK);
verifyEmail();
RegistryLock savedUnlockRequest =
getMostRecentRegistryLockByRepoId(defaultDomain.getRepoId()).get();
@@ -343,7 +346,7 @@ public class ConsoleRegistryLockActionTest {
.build();
action = createDefaultPostAction(false);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(response.getStatus()).isEqualTo(SC_OK);
verifyEmail();
}
@@ -356,7 +359,7 @@ public class ConsoleRegistryLockActionTest {
.build();
action = createPostAction("example.test", true, "", Optional.empty());
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(response.getStatus()).isEqualTo(SC_OK);
verifyEmail();
}
@@ -369,7 +372,7 @@ public class ConsoleRegistryLockActionTest {
.build();
action = createDefaultPostAction(true);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
}
@Test
@@ -386,14 +389,14 @@ public class ConsoleRegistryLockActionTest {
.build();
action = createDefaultPostAction(true);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
}
@Test
void testPost_failure_unlock_noLock() throws Exception {
action = createDefaultPostAction(false);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(response.getPayload()).isEqualTo("Domain example.test is already unlocked");
}
@@ -407,7 +410,7 @@ public class ConsoleRegistryLockActionTest {
persistResource(defaultDomain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
action = createDefaultPostAction(false);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(response.getPayload())
.isEqualTo("Non-admin user cannot unlock admin-locked domain example.test");
}
@@ -423,7 +426,7 @@ public class ConsoleRegistryLockActionTest {
action =
createPostAction("otherregistrar.test", true, "registryLockPassword", Optional.empty());
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(response.getPayload())
.isEqualTo("Domain otherregistrar.test is not owned by registrar TheRegistrar");
}
@@ -434,7 +437,7 @@ public class ConsoleRegistryLockActionTest {
loadRegistrar("TheRegistrar").asBuilder().setRegistryLockAllowed(false).build());
action = createDefaultPostAction(true);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(response.getPayload())
.isEqualTo("Registry lock not allowed for registrar TheRegistrar");
}
@@ -444,7 +447,7 @@ public class ConsoleRegistryLockActionTest {
user = user.asBuilder().setRegistryLockEmailAddress(null).build();
action = createDefaultPostAction(true);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(response.getPayload()).isEqualTo("User has no registry lock email address");
}
@@ -452,7 +455,7 @@ public class ConsoleRegistryLockActionTest {
void testPost_failure_badPassword() throws Exception {
action = createPostAction("example.test", true, "badPassword", Optional.empty());
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
assertThat(response.getStatus()).isEqualTo(SC_UNAUTHORIZED);
}
@Test
@@ -460,7 +463,7 @@ public class ConsoleRegistryLockActionTest {
saveRegistryLock(createDefaultLockBuilder().build());
action = createDefaultPostAction(true);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(response.getPayload())
.isEqualTo("A pending or completed lock action already exists for example.test");
}
@@ -470,7 +473,7 @@ public class ConsoleRegistryLockActionTest {
persistResource(defaultDomain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
action = createDefaultPostAction(true);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(response.getPayload()).isEqualTo("Domain example.test is already locked");
}
@@ -484,7 +487,7 @@ public class ConsoleRegistryLockActionTest {
.build());
action = createDefaultPostAction(false);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(response.getPayload()).isEqualTo("Domain example.test is already unlocked");
}
@@ -16,9 +16,10 @@ package google.registry.ui.server.console;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import static org.mockito.Mockito.when;
import com.google.api.client.http.HttpStatusCodes;
import com.google.gson.Gson;
import google.registry.model.console.User;
import google.registry.persistence.transaction.JpaTestExtensions;
@@ -67,8 +68,7 @@ class ConsoleUserDataActionTest {
ConsoleUserDataAction action =
createAction(Optional.of(FakeConsoleApiParams.get(Optional.of(authResult))));
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
Map jsonObject =
GSON.fromJson(((FakeResponse) consoleApiParams.response()).getPayload(), Map.class);
assertThat(jsonObject)
@@ -91,8 +91,7 @@ class ConsoleUserDataActionTest {
void testFailure_notAConsoleUser() throws IOException {
ConsoleUserDataAction action = createAction(Optional.empty());
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_UNAUTHORIZED);
}
private ConsoleUserDataAction createAction(Optional<ConsoleApiParams> maybeConsoleApiParams)
@@ -20,10 +20,12 @@ import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.persistNewRegistrar;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.SqlHelper.saveRegistrar;
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
@@ -99,10 +101,15 @@ class RegistrarsActionTest {
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
@Test
void testSuccess_onlyRealRegistrars() {
void testSuccess_onlyRealAndOteRegistrars() {
Registrar registrar = persistNewRegistrar("registrarId");
registrar = registrar.asBuilder().setType(Registrar.Type.TEST).setIanaIdentifier(null).build();
persistResource(registrar);
registrar = persistNewRegistrar("registrarId2");
registrar = registrar.asBuilder().setType(Registrar.Type.OTE).setIanaIdentifier(null).build();
persistResource(registrar);
RegistrarsAction action =
createAction(
Action.Method.GET,
@@ -111,14 +118,15 @@ class RegistrarsActionTest {
createUser(
new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_LEAD).build()))));
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
String payload = ((FakeResponse) consoleApiParams.response()).getPayload();
assertThat(
ImmutableList.of("\"registrarId\":\"NewRegistrar\"", "\"registrarId\":\"TheRegistrar\"")
.stream()
.allMatch(s -> payload.contains(s)))
.isTrue();
var actualRegistrarIds =
ImmutableList.copyOf(GSON.fromJson(payload, Registrar[].class)).stream()
.map(r -> r.getRegistrarId())
.collect(Collectors.toList());
assertThat(actualRegistrarIds).containsExactly("NewRegistrar", "TheRegistrar", "registrarId2");
}
@Test
@@ -131,8 +139,7 @@ class RegistrarsActionTest {
UserAuthInfo.create(
createUser(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()))));
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
String payload = ((FakeResponse) consoleApiParams.response()).getPayload();
assertThat(
ImmutableList.of(
@@ -152,8 +159,7 @@ class RegistrarsActionTest {
AuthResult.createUser(
UserAuthInfo.create(createUser(new UserRoles.Builder().setIsAdmin(true).build()))));
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
Registrar r = loadRegistrar("regIdTest");
assertThat(r).isNotNull();
assertThat(
@@ -183,7 +189,7 @@ class RegistrarsActionTest {
createUser(new UserRoles.Builder().setIsAdmin(true).build()))));
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
.isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
.isEqualTo(
String.format(
@@ -200,8 +206,7 @@ class RegistrarsActionTest {
AuthResult.createUser(
UserAuthInfo.create(createUser(new UserRoles.Builder().setIsAdmin(true).build()))));
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
.isEqualTo("Registrar with registrarId regIdTest already exists");
}
@@ -222,8 +227,7 @@ class RegistrarsActionTest {
RegistrarRole.ACCOUNT_MANAGER_WITH_REGISTRY_LOCK))
.build()))));
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_FORBIDDEN);
}
private User createUser(UserRoles userRoles) {
@@ -21,10 +21,11 @@ import static google.registry.testing.DatabaseHelper.createAdminUser;
import static google.registry.testing.DatabaseHelper.insertInDb;
import static google.registry.testing.DatabaseHelper.loadAllOf;
import static google.registry.testing.SqlHelper.saveRegistrar;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;
@@ -105,8 +106,7 @@ class ContactActionTest {
testRegistrar.getRegistrarId(),
null);
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
.isEqualTo("[" + jsonRegistrar1 + "]");
}
@@ -122,8 +122,7 @@ class ContactActionTest {
testRegistrar.getRegistrarId(),
null);
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload()).isEqualTo("[]");
}
@@ -136,8 +135,7 @@ class ContactActionTest {
testRegistrar.getRegistrarId(),
"[" + jsonRegistrar1 + "," + jsonRegistrar2 + "]");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
assertThat(
loadAllOf(RegistrarPoc.class).stream()
.filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId()))
@@ -157,8 +155,7 @@ class ContactActionTest {
testRegistrar.getRegistrarId(),
"[" + jsonRegistrar1 + "," + jsonRegistrar2 + "]");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
HashMap<String, String> testResult = new HashMap<>();
loadAllOf(RegistrarPoc.class).stream()
.filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId()))
@@ -181,8 +178,7 @@ class ContactActionTest {
testRegistrar.getRegistrarId(),
"[" + jsonRegistrar2 + "]");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
assertThat(
loadAllOf(RegistrarPoc.class).stream()
.filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId()))
@@ -212,8 +208,7 @@ class ContactActionTest {
testRegistrar.getRegistrarId(),
"[" + jsonRegistrar2 + "]");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_FORBIDDEN);
}
private ContactAction createAction(
@@ -19,10 +19,10 @@ import static google.registry.testing.CertificateSamples.SAMPLE_CERT2;
import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.SqlHelper.saveRegistrar;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.ImmutableSortedMap;
@@ -94,8 +94,7 @@ class SecurityActionTest {
UserAuthInfo.create(DatabaseHelper.createAdminUser("email@email.com"))),
testRegistrar.getRegistrarId());
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
Registrar r = loadRegistrar(testRegistrar.getRegistrarId());
assertThat(r.getClientCertificateHash().get())
.isEqualTo("GNd6ZP8/n91t9UTnpxR8aH7aAW4+CpvufYx9ViGbcMY");
@@ -16,10 +16,11 @@ package google.registry.ui.server.console.settings;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSetMultimap;
@@ -105,6 +106,10 @@ public class WhoisRegistrarFieldsActionTest {
ImmutableMap.of(
"whoisServer",
"whois.nic.google",
"phoneNumber",
"+1.4155552671",
"faxNumber",
"+1.4155552672",
"url",
"\"https://newurl.example\"",
"localizedAddress",
@@ -112,16 +117,18 @@ public class WhoisRegistrarFieldsActionTest {
+ " \"NL\", \"zip\": \"10011\", \"countryCode\": \"CA\"}"));
WhoisRegistrarFieldsAction action = createAction();
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
Registrar newRegistrar = Registrar.loadByRegistrarId("TheRegistrar").get(); // skip cache
assertThat(newRegistrar.getWhoisServer()).isEqualTo("whois.nic.google");
assertThat(newRegistrar.getUrl()).isEqualTo("https://newurl.example");
assertThat(newRegistrar.getLocalizedAddress().toJsonMap()).isEqualTo(addressMap);
assertThat(newRegistrar.getPhoneNumber()).isEqualTo("+1.4155552671");
assertThat(newRegistrar.getFaxNumber()).isEqualTo("+1.4155552672");
// the non-changed fields should be the same
assertAboutImmutableObjects()
.that(newRegistrar)
.isEqualExceptFields(oldRegistrar, "whoisServer", "url", "localizedAddress");
.isEqualExceptFields(
oldRegistrar, "whoisServer", "url", "localizedAddress", "phoneNumber", "faxNumber");
}
@Test
@@ -141,8 +148,7 @@ public class WhoisRegistrarFieldsActionTest {
uiRegistrarMap.put("registrarId", "NewRegistrar");
WhoisRegistrarFieldsAction action = createAction(onlyTheRegistrar);
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_FORBIDDEN);
// should be no change
assertThat(DatabaseHelper.loadByEntity(newRegistrar)).isEqualTo(newRegistrar);
}
@@ -24,9 +24,9 @@ import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.SqlHelper.saveRegistryLock;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static org.junit.jupiter.api.Assertions.assertThrows;
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;
@@ -110,7 +110,7 @@ final class RegistryLockGetActionTest {
action.authResult = AuthResult.createUser(UserAuthInfo.create(consoleUser));
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(GSON.fromJson(response.getPayload(), Map.class))
.containsExactly(
"status",
@@ -220,7 +220,7 @@ final class RegistryLockGetActionTest {
saveRegistryLock(unlockedLock);
action.run();
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(GSON.fromJson(response.getPayload(), Map.class))
.containsExactly(
"status", "SUCCESS",
@@ -261,11 +261,11 @@ td.section {
</tr>
<tr>
<td class="property_name">generated on</td>
<td class="property_value">2024-05-09 17:59:02.29076074</td>
<td class="property_value">2024-05-10 19:17:39.481284329</td>
</tr>
<tr>
<td class="property_name">last flyway file</td>
<td id="lastFlywayFile" class="property_value">V170__user_update_registry_lock_email.sql</td>
<td id="lastFlywayFile" class="property_value">V171__drop_create_billing_cost_columns_from_tld.sql</td>
</tr>
</tbody>
</table>
@@ -277,11 +277,11 @@ td.section {
SchemaCrawler_Diagram
</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-3493.5 4025,-3493.5 4025,4 -4,4" />
<text text-anchor="start" x="3737" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00">generated by</text>
<text text-anchor="start" x="3820" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00">SchemaCrawler 16.10.1</text>
<text text-anchor="start" x="3736" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">generated on</text>
<text text-anchor="start" x="3820" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">2024-05-09 17:59:02.29076074</text>
<polygon fill="none" stroke="#888888" points="3733,-4 3733,-44 4013,-44 4013,-4 3733,-4" /> <!-- allocationtoken_a08ccbef -->
<text text-anchor="start" x="3730.5" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00">generated by</text>
<text text-anchor="start" x="3813.5" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00">SchemaCrawler 16.10.1</text>
<text text-anchor="start" x="3729.5" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">generated on</text>
<text text-anchor="start" x="3813.5" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">2024-05-10 19:17:39.481284329</text>
<polygon fill="none" stroke="#888888" points="3726,-4 3726,-44 4013,-44 4013,-4 3726,-4" /> <!-- allocationtoken_a08ccbef -->
<g id="node1" class="node">
<title>
allocationtoken_a08ccbef
File diff suppressed because it is too large Load Diff
+1
View File
@@ -168,3 +168,4 @@ V167__creat_billing_cost_transitions_not_null.sql
V168__registry_lock_email.sql
V169__add_more_indexes_needed_for_delete_prober_data.sql
V170__user_update_registry_lock_email.sql
V171__drop_create_billing_cost_columns_from_tld.sql
@@ -0,0 +1,16 @@
-- Copyright 2024 The Nomulus Authors. All Rights Reserved.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
alter table "Tld" drop column create_billing_cost_amount;
alter table "Tld" drop column create_billing_cost_currency;
@@ -1249,8 +1249,6 @@ CREATE TABLE public."Tld" (
auto_renew_grace_period_length interval NOT NULL,
automatic_transfer_length interval NOT NULL,
claims_period_end timestamp with time zone NOT NULL,
create_billing_cost_amount numeric(19,2),
create_billing_cost_currency text,
creation_time timestamp with time zone NOT NULL,
currency text NOT NULL,
dns_paused boolean NOT NULL,
+1
View File
@@ -13,6 +13,7 @@ spec:
labels:
app: nomulus
spec:
serviceAccountName: nomulus
containers:
- name: nomulus
image: gcr.io/GCP_PROJECT/nomulus
+54
View File
@@ -0,0 +1,54 @@
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
apply plugin: 'java'
createUberJar('buildLoadTestClient', 'loadTest', 'google.registry.client.EppClient')
dependencies {
def deps = rootProject.dependencyMap
implementation deps['joda-time:joda-time']
implementation deps['io.netty:netty-buffer']
implementation deps['io.netty:netty-codec']
implementation deps['io.netty:netty-codec-http']
implementation deps['io.netty:netty-common']
implementation deps['io.netty:netty-handler']
implementation deps['io.netty:netty-transport']
implementation deps['com.google.guava:guava']
implementation deps['org.bouncycastle:bcpg-jdk18on']
implementation deps['org.bouncycastle:bcpkix-jdk18on']
implementation deps['org.bouncycastle:bcprov-jdk18on']
implementation deps['org.jcommander:jcommander']
implementation deps['com.google.flogger:flogger']
runtimeOnly deps['com.google.flogger:flogger-system-backend']
}
task makeStagingDirectory {
mkdir layout.buildDirectory.dir('stage')
}
task copyFilesToStaging(dependsOn: makeStagingDirectory, type: Copy) {
from layout.buildDirectory.file('libs/loadTest.jar'), "${projectDir}/certificate.pem", "${projectDir}/key.pem"
into layout.buildDirectory.dir('stage')
}
task deployLoadTestsToInstances (dependsOn: copyFilesToStaging, type: Exec) {
executable "sh"
workingDir "${projectDir}/"
args "-c", "./deploy.sh"
}
test {
useJUnitPlatform()
}
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
# Copyright 2024 The Nomulus Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
HOSTS=$(gcloud compute instances list | awk '/^loadtest/ { print $5 }')
for host in $HOSTS; do rsync -avz ./build/stage/ $host:test-client/; done
+19
View File
@@ -0,0 +1,19 @@
#!/bin/bash
# Copyright 2024 The Nomulus Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Find and delete the instances used for load testing
gcloud compute instances list --filter="name ~ loadtest.*" --zones us-east4-a \
--format="value(name)" | xargs gcloud compute instances delete --zone us-east4-a
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
# Copyright 2024 The Nomulus Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Create the instances - modify this number for the amount of instances you
# would like to use for your load test
gcloud compute instances create loadtest-{1..2} --machine-type g1-small \
--image-family ubuntu-2204-lts --image-project ubuntu-os-cloud --zone us-east4-a
sleep 10
# Get all the created load tests instances
HOSTS=$(gcloud compute instances list | awk '/^loadtest/ { print $5 }')
#Install rsync and Java - Retry is needed here since ssh connection will fail until instances are fully provisioned
for host in $HOSTS;
do
for i in {1..60}; do
if ssh $host 'sudo apt-get -y update &&
sudo apt-get -y upgrade &&
sudo apt-get -y install rsync &&
sudo apt-get -y install openjdk-21-jdk'; then
break
else
sleep 5
fi
done
done
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash
# Copyright 2024 The Nomulus Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
HOSTS=$(gcloud compute instances list | awk '/^loadtest/ { print $5 }')
for host in $HOSTS;
do ssh $host 'cd test-client/ &&
java -jar loadTest.jar --host epp.example --certificate certificate.pem -k key.pem -pw examplePassword -ft';
done
@@ -0,0 +1,353 @@
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.client;
import static com.google.common.io.Resources.getResource;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.joda.time.DateTimeZone.UTC;
import com.beust.jcommander.IStringConverter;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;
import com.google.common.io.Resources;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.Promise;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.joda.time.DateTime;
/** A simple EPP client that can be used for load testing. */
@Parameters(separators = " =")
@SuppressWarnings("FutureReturnValueIgnored")
public class EppClient implements Runnable {
static {
Security.addProvider(new BouncyCastleProvider());
}
private static final String LOGIN_FILE = "login.xml";
private static final String LOGOUT_FILE = "logout.xml";
static final AttributeKey<ArrayList<ZonedDateTime>> REQUEST_SENT =
AttributeKey.valueOf("REQUEST_SENT");
static final AttributeKey<ArrayList<ZonedDateTime>> RESPONSE_RECEIVED =
AttributeKey.valueOf("RESPONSE_RECEIVED");
static final AttributeKey<Integer> CHANNEL_NUMBER = AttributeKey.valueOf("CHANNEL_NUMBER");
static final AttributeKey<Path> LOGGING_LOCATION = AttributeKey.valueOf("LOGGING_LOCATION");
static final AttributeKey<Boolean> FORCE_TERMINATE = AttributeKey.valueOf("FORCE_TERMINATE");
static final AttributeKey<ExecutorService> LOGGING_EXECUTOR =
AttributeKey.valueOf("LOGGING_EXECUTOR");
static final AttributeKey<Iterator<byte[]>> INPUT_ITERATOR =
AttributeKey.valueOf("INPUT_ITERATOR");
static final AttributeKey<Promise<Void>> LOGGING_REQUEST_COMPLETE =
AttributeKey.valueOf("LOGGING_REQUEST_COMPLETE");
private static final int PORT = 700;
private static final int TIMEOUT_SECONDS = 600;
public static class InetAddressConverter implements IStringConverter<InetAddress> {
@Override
public InetAddress convert(String host) {
try {
return InetAddress.getByName(host);
} catch (UnknownHostException e) {
throw new IllegalArgumentException(host, e);
}
}
}
@Parameter(
names = {"--help"},
description = "Print this help message.",
help = true)
private boolean help = false;
@Parameter(
names = {"--host", "-h"},
description = "Epp server hostname/IP to connect to.",
converter = InetAddressConverter.class,
required = true)
private InetAddress host = null;
@Parameter(
names = {"--certificate"},
description = "Certificate pem file.",
required = true)
private String certFileName = null;
@Parameter(
names = {"--key", "-k"},
description = "Private key pem file.",
required = true)
private String keyFileName = null;
@Parameter(
names = {"--connections", "-cn"},
description = "Number of connections that are made to the EPP server.")
private int connections = 1;
@Parameter(
names = {"--client", "-c"},
description = "Registrar client id.")
private String client = "proxy";
@Parameter(
names = {"--password", "-pw"},
description = "Registrar password.")
private String password = "abcde12345";
@Parameter(
names = {"--force_terminate", "-ft"},
description = "Whether to explicitly close the connection after receiving a logout response.")
private boolean forceTerminate = false;
public static void main(String[] args) {
EppClient eppClient = new EppClient();
JCommander jCommander = new JCommander(eppClient);
jCommander.parse(args);
if (eppClient.help) {
jCommander.usage();
return;
}
eppClient.run();
}
private ImmutableList<String> makeInputList(ZonedDateTime now) {
ImmutableList.Builder<String> templatesList = ImmutableList.builder();
ImmutableList.Builder<String> inputList = ImmutableList.builder();
templatesList.add(readStringFromFile(LOGIN_FILE));
templatesList.add(readStringFromFile(LOGOUT_FILE));
for (String template : templatesList.build()) {
inputList.add(
template
.replace("@@CLIENT@@", client)
.replace("@@PASSWORD@@", password)
.replace("@@NOW@@", now.toString()));
}
return inputList.build();
}
private static String readStringFromFile(String filename) {
try {
return Resources.toString(getResource(EppClient.class, "resources/" + filename), UTF_8);
} catch (IOException e) {
throw new IllegalArgumentException("Cannot read from file: resources/" + filename);
}
}
private static KeyPair getKeyPair(String filename) throws IOException {
byte[] keyBytes = Files.asCharSource(new File(filename), UTF_8).read().getBytes(UTF_8);
try {
PEMKeyPair pemPair =
(PEMKeyPair)
new PEMParser(new InputStreamReader(new ByteArrayInputStream(keyBytes), UTF_8))
.readObject();
return new JcaPEMKeyConverter().setProvider("BC").getKeyPair(pemPair);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static X509Certificate getCertificate(String filename) throws IOException {
byte[] certificateBytes = Files.asCharSource(new File(filename), UTF_8).read().getBytes(UTF_8);
try {
X509CertificateHolder certificateHolder =
(X509CertificateHolder)
new PEMParser(
new InputStreamReader(new ByteArrayInputStream(certificateBytes), UTF_8))
.readObject();
return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certificateHolder);
} catch (IOException | CertificateException e) {
throw new RuntimeException(e);
}
}
private ChannelInitializer<SocketChannel> makeChannelInitializer(
String outputFolder, ImmutableList<ExecutorService> loggingExecutors) throws IOException {
return new ChannelInitializer<>() {
private final ImmutableList<String> inputList =
makeInputList(ZonedDateTime.now(ZoneOffset.UTC));
private final KeyPair key = getKeyPair(keyFileName);
private final X509Certificate cert = getCertificate(certFileName);
private final LoggingHandler loggingHandler = new LoggingHandler(LogLevel.INFO);
private final EppClientHandler eppClientHandler = new EppClientHandler();
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.attr(REQUEST_SENT).set(new ArrayList<>());
ch.attr(RESPONSE_RECEIVED).set(new ArrayList<>());
Path loggingLocation =
Paths.get(String.format("%s/%d.log", outputFolder, ch.attr(CHANNEL_NUMBER).get()));
ch.attr(LOGGING_LOCATION).set(loggingLocation);
ch.attr(FORCE_TERMINATE).set(forceTerminate);
ch.attr(LOGGING_EXECUTOR)
.set(loggingExecutors.get(ch.attr(CHANNEL_NUMBER).get() % loggingExecutors.size()));
ch.attr(INPUT_ITERATOR)
.set(
inputList.stream()
.map(
(String str) ->
str.replace(
"@@CHANNEL_NUMBER@@",
String.valueOf(ch.attr(CHANNEL_NUMBER).get()))
.replace("@@CHANNEL_NUMBER_MODULO@@", String.valueOf(0))
.getBytes(UTF_8))
.iterator());
ch.pipeline()
.addLast(
SslContextBuilder.forClient()
.keyManager(key.getPrivate(), cert)
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build()
.newHandler(ch.alloc(), host.getHostName(), PORT));
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(512 * 1024, 0, 4, -4, 4));
ch.pipeline().addLast(new LengthFieldPrepender(4, true));
ch.pipeline().addLast(loggingHandler);
ch.pipeline().addLast(eppClientHandler);
}
};
}
private static String createOutputFolder(String folderName) {
Path folder = Paths.get(folderName);
if (!folder.toFile().exists()) {
folder.toFile().mkdirs();
}
System.out.printf("\nOutputs saved at %s\n", folder);
return folderName;
}
@Override
public void run() {
String outputFolder = createOutputFolder(String.format("load-tests/%s", DateTime.now(UTC)));
ImmutableList.Builder<ExecutorService> builder = ImmutableList.builderWithExpectedSize(5);
for (int i = 0; i < 5; ++i) {
builder.add(Executors.newSingleThreadExecutor());
}
final ImmutableList<ExecutorService> loggingExecutors = builder.build();
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap =
new Bootstrap()
.group(eventLoopGroup)
.channel(NioSocketChannel.class)
.handler(makeChannelInitializer(outputFolder, loggingExecutors));
List<ChannelFuture> channelFutures = new ArrayList<>();
// Three requests: hello (from the proxy), login and logout.
int requestPerConnection = 3;
for (int i = 0; i < connections; i++) {
bootstrap.attr(CHANNEL_NUMBER, i);
channelFutures.add(
bootstrap
.connect(host, PORT)
.addListener(
(ChannelFuture cf) -> {
if (!cf.isSuccess()) {
System.out.printf("Cannot connect to %s:%s\n", host, PORT);
}
}));
}
LinkedHashSet<Integer> killedConnections = new LinkedHashSet<>();
// Wait for all channels to close.
for (ChannelFuture channelFuture : channelFutures) {
Channel channel = channelFuture.syncUninterruptibly().channel();
int channelNumber = channel.attr(CHANNEL_NUMBER).get();
if (!channel
.closeFuture()
.awaitUninterruptibly(
TIMEOUT_SECONDS * 1000
- Duration.between(
channel.attr(REQUEST_SENT).get().getFirst(),
ZonedDateTime.now(ZoneOffset.UTC))
.toMillis())) {
channel.close().syncUninterruptibly();
killedConnections.add(channelNumber);
}
}
System.out.println();
System.out.println("====== SUMMARY ======");
System.out.printf("Number of connections: %d\n", connections);
System.out.printf("Number of requests per connection: %d\n", requestPerConnection);
if (!killedConnections.isEmpty()) {
System.out.printf("Force killed connections (%d): ", killedConnections.size());
for (int channelNumber : killedConnections) {
System.out.printf("%d ", channelNumber);
}
System.out.print("\n");
}
eventLoopGroup.shutdownGracefully();
channelFutures.forEach(
channelFuture -> {
channelFuture.channel().attr(LOGGING_REQUEST_COMPLETE).get().syncUninterruptibly();
});
loggingExecutors.forEach(ExecutorService::shutdown);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@@ -0,0 +1,153 @@
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.client;
import static google.registry.client.EppClient.CHANNEL_NUMBER;
import static google.registry.client.EppClient.FORCE_TERMINATE;
import static google.registry.client.EppClient.INPUT_ITERATOR;
import static google.registry.client.EppClient.LOGGING_EXECUTOR;
import static google.registry.client.EppClient.LOGGING_LOCATION;
import static google.registry.client.EppClient.LOGGING_REQUEST_COMPLETE;
import static google.registry.client.EppClient.REQUEST_SENT;
import static google.registry.client.EppClient.RESPONSE_RECEIVED;
import static java.nio.file.StandardOpenOption.APPEND;
import com.google.common.flogger.FluentLogger;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.Promise;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
/** Handler that sends EPP requests and receives EPP responses. */
@SuppressWarnings("FutureReturnValueIgnored")
@Sharable
public class EppClientHandler extends ChannelDuplexHandler {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
static class FileWriter implements Runnable {
private final Path loggingLocation;
private final byte[] contents;
private final ZonedDateTime time;
FileWriter(Path loggingLocation, byte[] contents, ZonedDateTime time) {
this.loggingLocation = loggingLocation;
this.contents = contents;
this.time = time;
}
@Override
public void run() {
try {
if (!Files.exists(loggingLocation)) {
Files.createFile(loggingLocation);
}
Files.writeString(loggingLocation, time.toString() + "\n", APPEND);
Files.write(loggingLocation, contents, APPEND);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
ctx.channel().attr(REQUEST_SENT).get().add(now);
ctx.channel().attr(LOGGING_REQUEST_COMPLETE).set(ctx.executor().newPromise());
super.channelRegistered(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
Promise<Void> loggingCompletePromise = ctx.channel().attr(LOGGING_REQUEST_COMPLETE).get();
if (!loggingCompletePromise.isDone()) {
loggingCompletePromise.setSuccess(null);
}
logger.atWarning().withCause(cause).log(
"Connection %d closed.", ctx.channel().attr(CHANNEL_NUMBER).get());
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
Channel ch = ctx.channel();
ctx.channel().attr(RESPONSE_RECEIVED).get().add(now);
if (msg instanceof ByteBuf buffer) {
byte[] contents = new byte[buffer.readableBytes()];
buffer.readBytes(contents);
ReferenceCountUtil.release(buffer);
if (ch.attr(LOGGING_LOCATION).get() != null) {
ch.attr(LOGGING_EXECUTOR)
.get()
.submit(new FileWriter(ch.attr(LOGGING_LOCATION).get(), contents, now));
}
if (ch.attr(INPUT_ITERATOR).get().hasNext()) {
ch.writeAndFlush(ch.attr(INPUT_ITERATOR).get().next());
} else {
ch.attr(LOGGING_REQUEST_COMPLETE).get().setSuccess(null);
if (ch.attr(FORCE_TERMINATE).get()) {
ch.close();
}
}
}
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
Channel ch = ctx.channel();
ctx.channel().attr(REQUEST_SENT).get().add(now);
if (msg instanceof byte[] outputBytes) {
ByteBuf buffer = Unpooled.buffer();
buffer.writeBytes(outputBytes);
ctx.write(buffer, promise);
if (ch.attr(LOGGING_LOCATION).get() != null) {
ch.attr(LOGGING_EXECUTOR)
.get()
.submit(new FileWriter(ch.attr(LOGGING_LOCATION).get(), outputBytes, now));
}
}
}
@Override
public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
Promise<Void> loggingCompletePromise = ctx.channel().attr(LOGGING_REQUEST_COMPLETE).get();
if (!loggingCompletePromise.isDone()) {
loggingCompletePromise.setSuccess(null);
}
super.close(ctx, promise);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
Promise<Void> loggingCompletePromise = ctx.channel().attr(LOGGING_REQUEST_COMPLETE).get();
if (!loggingCompletePromise.isDone()) {
loggingCompletePromise.setSuccess(null);
}
super.channelInactive(ctx);
}
}
@@ -0,0 +1,73 @@
## EPP Load Testing Client
This project contains an EPP client that can be use for load testing the full
registry platform. All the below commands should be run from the merged root.
### Setting up the test instances
* If you have not done s yet, you will need to set up ssh keys in your
[GCE metadata](https://pantheon.corp.google.com/compute/metadata?resourceTab=sshkeys):
* To create however many GCE instances you want to run on, modify the
`instanceSetUp.sh` file to include the correct number of instances.
* Run the instance set up script to create and configure each of the GCE
instances to be used for load testing:
```shell
$ load-testing/instanceSetUp.sh
```
* Verify that the IP address of any created instances is in the allowlist of the
proxy registrar user.
* Use the below command to get the IP addresses of the created instances.
```shell
$ (gcloud compute instances list | awk '/^loadtest/ { print $5 }')
```
* Check the proxy registrar's current allow list
```shell
$ nomulus -e sandbox get_registrar proxy | grep ipAddressAllowList
```
* All of your host ip addresses should match a netmask specified in the proxy
allow list. If not, you'll need to redefine the list:
```shell
$ nomulus -e sandbox update_registrar proxy --ip_allow_list=<new-comma-separated-allowlist>
```
### Running the client
* From the merged root build the load testing client:
```shell
$ ./nom_build :load-testing:buildLoadTestClient
```
* Deploy the client to the GCE instances (this will create a local staging
directory and deploy it to each of your previously created loadtest GCE instances):
```shell
$ ./nom_build :load-testing:deployLoadTestsToInstances
```
* Run the load test. Configurations of the load test can be made by configuring
this `run.sh` file locally.
```shell
$ load-testing/run.sh
```
### Cleanup
* Run the instance clean up script to delete the created instances
```shell
$ load-testing/instanceCleanUp.sh
```
* You may want to remove any host key fingerprints for those hosts from your ~/.ssh/known_hosts file (these IPs tend to get reused with new host keys)
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<login>
<clID>@@CLIENT@@</clID>
<pw>@@PASSWORD@@</pw>
<options>
<version>1.0</version>
<lang>en</lang>
</options>
<svcs>
<objURI>urn:ietf:params:xml:ns:host-1.0</objURI>
<objURI>urn:ietf:params:xml:ns:domain-1.0</objURI>
<objURI>urn:ietf:params:xml:ns:contact-1.0</objURI>
</svcs>
</login>
<clTRID>epp-client-login-@@NOW@@-@@CHANNEL_NUMBER@@</clTRID>
</command>
</epp>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<logout/>
<clTRID>epp-client-logout-@@NOW@@-@@CHANNEL_NUMBER@@</clTRID>
</command>
</epp>
+1
View File
@@ -47,3 +47,4 @@ include 'services:tools'
include 'services:pubapi'
include 'console-webapp'
include 'jetty'
include 'load-testing'
@@ -57,6 +57,16 @@ public class GcpJsonFormatter extends Formatter {
/** JSON field that contains the content, this will show up as the main entry in a log. */
private static final String MESSAGE = "message";
/**
* JSON field that contains the stack trace, if any.
*
* <p>Note that this field is not part of the structured logging that stackdriver understands.
* Normally we'd just append the stack trace to the message itself. However, for unclear reasons,
* if we do that on GKE, the log entry containing a stack trace will be lumped together with
* several following log entries and makes it hard to read.
*/
private static final String STACKTRACE = "stacktrace";
private static final String FILE = "file";
private static final String FUNCTION = "function";
@@ -99,16 +109,17 @@ public class GcpJsonFormatter extends Formatter {
String severity = severityFor(record.getLevel());
// The rest is mostly lifted from java.util.logging.SimpleFormatter.
String stacktrace = "";
String throwable = "";
if (record.getThrown() != null) {
StringWriter sw = new StringWriter();
try (PrintWriter pw = new PrintWriter(sw)) {
pw.println();
record.getThrown().printStackTrace(pw);
}
stacktrace = sw.toString();
PrintWriter pw = new PrintWriter(sw);
pw.println();
record.getThrown().printStackTrace(pw);
pw.close();
throwable = sw.toString();
}
String message = '\n' + record.getMessage() + stacktrace;
String message = '\n' + formatMessage(record);
String function = "";
if (record.getSourceClassName() != null) {
@@ -144,6 +155,9 @@ public class GcpJsonFormatter extends Formatter {
json.put(SEVERITY, severity);
json.put(SOURCE_LOCATION, sourceLocation);
json.put(MESSAGE, message);
if (!throwable.isEmpty()) {
json.put(STACKTRACE, throwable);
}
if (traceId.get() != null) {
json.put(TRACE, traceId.get());
}
@@ -109,14 +109,11 @@ class GcpJsonFormatterTest {
handler.close();
String output = ostream.toString(StandardCharsets.US_ASCII);
String prefix =
makeJson(
"ERROR",
108,
"testSuccess_withCause",
"Something went terribly wrong\\njava.lang.RuntimeException: boom!");
// Remove the last three characters (", }, \n) from the template as the actual output contains
makeJson("ERROR", 108, "testSuccess_withCause", "Something went terribly wrong");
// Remove the last two characters (}, \n) from the template as the actual output contains
// the full stack trace.
prefix = prefix.substring(0, prefix.length() - 3);
prefix = prefix.substring(0, prefix.length() - 2);
prefix += ",\"stacktrace\":\"\\njava.lang.RuntimeException: boom!\\n";
assertThat(output).startsWith(prefix);
}
@@ -126,14 +123,11 @@ class GcpJsonFormatterTest {
handler.close();
String output = ostream.toString(StandardCharsets.US_ASCII);
String prefix =
makeJson(
"ERROR",
125,
"testSuccess_withStackTrace",
"Something is worth checking\\ncom.google.common.flogger.LogSiteStackTrace: FULL");
// Remove the last three characters (", }, \n) from the template as the actual output contains
makeJson("ERROR", 122, "testSuccess_withStackTrace", "Something is worth checking");
// Remove the last three characters (}, \n) from the template as the actual output contains
// the full stack trace.
prefix = prefix.substring(0, prefix.length() - 3);
prefix = prefix.substring(0, prefix.length() - 2);
prefix += ",\"stacktrace\":\"\\ncom.google.common.flogger.LogSiteStackTrace: FULL\\n";
assertThat(output).startsWith(prefix);
}