1
0
mirror of https://github.com/google/nomulus synced 2026-05-21 07:11:48 +00:00

Compare commits

...

56 Commits

Author SHA1 Message Date
gbrodman
21950f7d82 Add a bulk-domain-action console endpoint (#2611)
For now it only includes two options (domain deletion and domain
suspension). In the future, as necessary, we can add other actions but
this seems like a relatively simple starting point (actions like bulk
updates are much more conceptually complex).
2024-11-22 20:47:47 +00:00
Ben McIlwain
e66aee0416 Downgrade the tx isolation level of poll message ack flow (#2615)
This might help alleviate DB transaction contention on the PollMessage table. A
lower transaction isolation level is safe because acking a poll message is
idempotent: there are only two things it does, either delete a poll message or
take a recurring one from the past and set it to be a year in the future from
the date in the past. Both of these operations will always yield the same final
result even if executed multiple times simultaneously for some reason.
2024-11-22 19:48:19 +00:00
Ben McIlwain
c7e1fc17d2 Downgrade the tx isolation level of poll message request flow (#2614)
It doesn't need a higher transaction isolation level as it's only loading a given poll
message once, and we want to avoid putting any kind of locks on the PollMessage table
as it seems to be having contention issues. Note that the poll message request flow
is by far the most frequent code that touches the PollMessage table, as there are many
many requests every minute from dozens of registrars, but much fewer poll messages
than that to actually ACK.
2024-11-21 22:49:57 +00:00
gbrodman
0c0b0df36e Skip poll messages on deletions for configured registrars (#2613)
See b/379331882 for more details
2024-11-21 22:16:26 +00:00
Weimin Yu
304f0002b4 Refactor FlowRunner transaction invocation (#2612)
Stop calling `transact` if already in a transaction.
2024-11-21 15:58:26 +00:00
gbrodman
15cf3e1bc0 Add RegistrarUpdateHistory objects for console changes (#2585) 2024-11-19 21:03:48 +00:00
Pavlo Tkach
eeed166310 Add console user role update and minor fixes to delete (#2610) 2024-11-15 18:36:10 +00:00
gbrodman
e54075fea3 Allow for removal of registry lock passwords in User objects (#2609)
This essentially enables the "forgot password" flow
2024-11-14 21:01:17 +00:00
Ben McIlwain
78cc1b2937 Fix 'Domian' typo for Domain (#2608) 2024-11-12 18:41:56 +00:00
Pavlo Tkach
35f95bbbe4 Add delete user to the console (#2603)
* Add delete user to the console

* Add delete user to the console

* Add delete user to the console
2024-11-08 18:20:01 +00:00
gbrodman
ae61cd443d Sometimes include deletion times in domain-list exports (#2602)
We only include the deletion time if the domain is in the 5-day
PENDING_DELETE period after the 30 day REDEMPTION period. For all other
domains, we just have an empty string as that field.

This is behind a feature flag so that we can control when it is enabled
2024-11-06 17:59:30 +00:00
gbrodman
cc20f7d76d Add a simple toString for TimedTransitionProperty (#2604)
this means that we can actually see the transitions when running
GetAllocationTokenCommand, for instance
2024-11-05 18:26:36 +00:00
Ben McIlwain
5603b91526 Make nomulus update_recurrence command only fail on pending transfers (#2605)
It was failing when any kind of transfer data was present, even completed
transfer data. Note that completed transfer data persists on a domain
indefinitely until/unless a new transfer is requested.

BUG= http://b/377328244
2024-11-04 21:16:11 +00:00
Pavlo Tkach
332f491ac7 Fix cut off status list on domains page (#2601) 2024-10-28 18:20:04 +00:00
Pavlo Tkach
4bd7c18fe9 Add console settings update progress status (#2596) 2024-10-25 22:23:22 +00:00
Pavlo Tkach
fdb0664841 Add admin.directory.user.security scope (#2597) 2024-10-25 21:24:15 +00:00
Lai Jiang
a9ba770bfa Add canary service to GKE (#2594) 2024-10-22 17:12:00 +00:00
Lai Jiang
4d96e5a6b1 Remove cap on soy (#2592)
We still need to cap the protobuf version that soy depends on, but the
rest of nomulus can use the latest version of protobuf.
2024-10-18 17:21:26 +00:00
Lai Jiang
1171c5cfcb Delete legacy console (#2579) 2024-10-17 20:48:10 +00:00
Pavlo Tkach
91e241374d Add required fields to API users().insert (#2593) 2024-10-17 19:45:12 +00:00
Weimin Yu
634202c0e9 A batch query utility to replace TransactionManager's loadAllOf methods (#2589)
* Replace  with batch query

* Addressing CR
2024-10-14 20:11:29 +00:00
Lai Jiang
020ed33003 Fix releases (#2591)
It seems like `/usr/bin/python` is no longer symlinked to the `python3`
binary in the `gcr.io/cloud-builders/git` image.

I've sent out a separate fix to upstream to change the shebang.

https://gerrit-review.git.corp.google.com/c/gcompute-tools/+/439501

But in the meantime, we need this temporary fix for the release to
build.
2024-10-14 15:42:15 +00:00
dependabot[bot]
0f61066b1d Bump the npm_and_yarn group in /console-webapp with 3 updates (#2588)
Bumps the npm_and_yarn group in /console-webapp with 3 updates: [cookie](https://github.com/jshttp/cookie), [socket.io](https://github.com/socketio/socket.io) and [express](https://github.com/expressjs/express).


Updates `cookie` from 0.4.2 to 0.7.2
- [Release notes](https://github.com/jshttp/cookie/releases)
- [Commits](https://github.com/jshttp/cookie/compare/v0.4.2...v0.7.2)

Updates `socket.io` from 4.7.5 to 4.8.0
- [Release notes](https://github.com/socketio/socket.io/releases)
- [Changelog](https://github.com/socketio/socket.io/blob/main/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io/compare/socket.io@4.7.5...socket.io@4.8.0)

Updates `express` from 4.21.0 to 4.21.1
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.1/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.21.0...4.21.1)

---
updated-dependencies:
- dependency-name: cookie
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: socket.io
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: express
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Lai Jiang <jianglai@google.com>
2024-10-11 01:38:56 +00:00
Pavlo Tkach
03711481cd Fix console screenshot tests flakiness (#2590) 2024-10-10 21:17:42 +00:00
gbrodman
c32fb2fc71 Add screenshot tests for the new registrar console (#2577)
This required updating to a newer version of Selenium, building the
console dist/ folder, and serving that folder.
2024-10-09 16:44:34 +00:00
Pavlo Tkach
6e77c89cd6 Add console users screen (#2576) 2024-10-08 16:00:47 +00:00
Lai Jiang
5e41e84b8d Upgrade avro version (#2587)
Per b/371714822.
2024-10-07 15:43:53 +00:00
Lai Jiang
bfd569ee44 Add Aman to CONTRIBUTORS (#2586)
Give credit where credit it due @sanger2000.
2024-10-04 22:46:25 +00:00
Lai Jiang
b13a33347f Add Juan to CONTRIBUTORS (#2584) 2024-10-03 23:59:10 +00:00
Lai Jiang
d17a6edf12 Try to fix CodeQL java actions (#2583)
These flags are suggested by GitHub support to disable reusing caches
during Gradle build. They think that could fix the intermittent error
message:

```
Encountered a fatal error while running "/opt/hostedtoolcache/CodeQL/2.19.0/x64/codeql/codeql database finalize --finalize-dataset --threads=4 --ram=14576 --verbosity=progress++ /home/runner/work/_temp/codeql_databases/java". Exit code was 32 and last log line was: CodeQL detected code written in Java/Kotlin but could not process any of it. For more information, review our troubleshooting guide at https://gh.io/troubleshooting-code-scanning/no-source-code-seen-during-build . See the logs for more details.
```
2024-10-03 19:54:26 +00:00
Lai Jiang
7255ebff29 Fix a redirect bug (#2582) 2024-10-03 16:51:54 +00:00
Pavlo Tkach
cacc90097a Set POST method to SyncRegistrarSheetAction invocation (#2580) 2024-10-02 15:32:38 +00:00
Lai Jiang
0ef8984767 Remove schedule CodeQL run (#2581)
This fails for me every day for some reason (starting about a month
ago). The same commit went through the workflow fine when the action was
triggered by a push.

I think there's no reason for us to have a cron run as the changes to the
master branch can only come from commit pushes.
2024-10-02 15:29:55 +00:00
Juan Celhay
7a4abd93dc Add discount price param to GenerateAllocationTokens command (#2578)
* Add discount price param to GenerateAlloCationTokens command

* add discount price param to UpdateAllocationTokens command
2024-10-01 22:20:21 +00:00
Lai Jiang
142c910e3b Disable legacy registrar console (#2575) 2024-10-01 19:42:35 +00:00
gbrodman
c68d54a5ed Don't show snackbar on rlock-load failure if 403 (#2574)
ACCOUNT_MANAGER users don't have permission to see locks so it'll throw
403s. That's OK, we don't need/want to display that error to the client.
2024-09-30 20:42:33 +00:00
Pavlo Tkach
d17188b820 Add console users action (#2573) 2024-09-30 15:39:38 +00:00
Lai Jiang
cbe59b6950 Upgrade to use Gradle setup-gradle v4 (#2569)
I have seen a lot of CodeQL errors recently for no apparent reason.
Hopefully this will fix them.
2024-09-26 20:45:07 +00:00
Ben McIlwain
2b3c6525ff Add some basic info logging to RefreshDnsForAllDomainsAction (#2572)
BUG=http://b/369842541
2024-09-26 19:03:08 +00:00
Lai Jiang
72dd8658cf Upgrade to Gradle 8.10.2 (#2571) 2024-09-26 17:53:45 +00:00
Lai Jiang
c0490f7777 Update google-java-format (#2570)
Also converted regex strings in the Python script to raw strings as
future Python versions will start to reject them.

See: https://docs.python.org/3/whatsnew/3.12.html#other-language-changes
2024-09-26 14:49:38 +00:00
Lai Jiang
a22a38527b Make GPG related tests work with the latest version of GPG (#2568)
Newer versions of GPG (v.2.4.5 in my case) has uses different wording
then what's available in our build image (and Ubuntu I suspect). For
example it says "rsa2048" instead of "2048-bit RSA".

Make the tests work in both cases. Admittedly we cannot check for the
string RSA/rsa easily, but I don't think it matters much for tests.
2024-09-26 14:10:07 +00:00
Lai Jiang
08203033a2 Make the db object sync job more reliable (#2567)
It looks like /usr/bin/python *may* no longer exists in the latest cloud
builder git image. I ran the latest image and logged into it to verify
that /usr/bin/python3 does exist on 9/25, and again on 9/26 where it
re-appeared.

I think it is generally a good idea to not rely on it being there going
forward.
2024-09-26 02:10:00 +00:00
dependabot[bot]
d0482a8f2c Bump rollup in /console-webapp in the npm_and_yarn group (#2566)
Bumps the npm_and_yarn group in /console-webapp with 1 update: [rollup](https://github.com/rollup/rollup).


Updates `rollup` from 4.16.4 to 4.22.4
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.16.4...v4.22.4)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-25 18:47:21 +00:00
Juan Celhay
e6a2db8075 Add discount price to AllocationToken (#2559)
* Include discount price in domai n pricing

* Partial progress in logic

* Tests and logic passing

* Change pricing for multi year create

* Tests for discount pricing logic

* Token currency check

* Add some comments

* Java formatting

* Discount price to Optional

* Change discount price to be optional nullable

* Re-add deleted tests
2024-09-23 20:18:33 +00:00
Lai Jiang
7929322e95 Connect to the correct endpoints based on runtime (#2540)
* Connect to the correct endpoints based on runtime

* Address code review comments

* Add checks for HTTP methods
2024-09-20 18:39:54 +00:00
Lai Jiang
5c35811eb9 Upgrade protobuf (#2565)
Patched from https://github.com/google/nomulus/pull/2564.

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-20 17:56:53 +00:00
Weimin Yu
4ba0f4a2cd Change nested transact calls to retransact (#2563) 2024-09-20 15:16:52 +00:00
Lai Jiang
e167b4b753 Make the cloud scheduler deployer GKE-aware (#2562)
Depending on if a "--gke" parameter (must be the last one) is passed,
the deployer constructs the corresponding URIs for GAE or GKE
accordingly.

TESTED=Used the deployer to deploy tasks to alpha and verified that they
run on GKE.
2024-09-19 16:28:08 +00:00
Joaquin Gimenez
c47f821754 Fix typo in docs (#2520) 2024-09-18 18:57:27 +00:00
Weimin Yu
febdbc0468 Drop the transact call in IdService (#2561)
* Drop the `transact` call in Id services

All usages already routed through `tm().allocateId()`, which is
guaranteed to be in a transaction.

* Addressing reviews
2024-09-18 18:18:36 +00:00
dependabot[bot]
a988732d65 Bump the npm_and_yarn group in /console-webapp with 5 updates (#2560)
Bumps the npm_and_yarn group in /console-webapp with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [body-parser](https://github.com/expressjs/body-parser) | `1.20.2` | `1.20.3` |
| [express](https://github.com/expressjs/express) | `4.19.2` | `4.21.0` |
| [path-to-regexp](https://github.com/pillarjs/path-to-regexp) | `0.1.7` | `0.1.10` |
| [send](https://github.com/pillarjs/send) | `0.18.0` | `0.19.0` |
| [serve-static](https://github.com/expressjs/serve-static) | `1.15.0` | `1.16.2` |


Updates `body-parser` from 1.20.2 to 1.20.3
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3)

Updates `express` from 4.19.2 to 4.21.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0)

Updates `express` from 4.19.2 to 4.21.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0)

Updates `path-to-regexp` from 0.1.7 to 0.1.10
- [Release notes](https://github.com/pillarjs/path-to-regexp/releases)
- [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md)
- [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.7...v0.1.10)

Updates `send` from 0.18.0 to 0.19.0
- [Release notes](https://github.com/pillarjs/send/releases)
- [Changelog](https://github.com/pillarjs/send/blob/master/HISTORY.md)
- [Commits](https://github.com/pillarjs/send/compare/0.18.0...0.19.0)

Updates `serve-static` from 1.15.0 to 1.16.2
- [Release notes](https://github.com/expressjs/serve-static/releases)
- [Changelog](https://github.com/expressjs/serve-static/blob/v1.16.2/HISTORY.md)
- [Commits](https://github.com/expressjs/serve-static/compare/v1.15.0...v1.16.2)

---
updated-dependencies:
- dependency-name: body-parser
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: express
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: express
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: path-to-regexp
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: send
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: serve-static
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-17 22:40:24 +00:00
Juan Celhay
7ee541e1b1 Add activeOrDeletedSince parameter to RefreshDnsForAllDomainsAction (#2556) 2024-09-17 16:02:25 +00:00
Lai Jiang
b07769bdee Switch to new jaxb runtime (#2558) 2024-09-16 22:39:59 +00:00
Weimin Yu
9db016638e Use repeatable-read in some batch actions (#2557) 2024-09-16 18:56:33 +00:00
Weimin Yu
c3d164d462 CheckApi should use replica (#2554) 2024-09-16 16:10:28 +00:00
436 changed files with 6411 additions and 10253 deletions

View File

@@ -6,8 +6,6 @@ on:
pull_request:
# The branches below must be a subset of the branches above
branches: [ 'master' ]
schedule:
- cron: '24 4 * * *'
jobs:
analyze:
@@ -49,13 +47,13 @@ jobs:
# Build with Gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
uses: gradle/actions/setup-gradle@v4
with:
build-scan-publish: true
build-scan-terms-of-service-url: "https://gradle.com/terms-of-service"
build-scan-terms-of-service-agree: "yes"
build-scan-terms-of-use-url: "https://gradle.com/terms-of-service"
build-scan-terms-of-use-agree: "yes"
- name: Execute Gradle build
run: ./gradlew build -x test -x jIFC
run: ./gradlew --no-daemon --no-build-cache --no-configuration-cache --rerun-tasks clean build -x test -x jIFC
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)

View File

@@ -34,6 +34,8 @@ Guy Bensky <guyben@google.com>
Weimin Yu <weiminyu@google.com>
Shicong Huang <shicong@google.com>
Gustav Brodman <gbrodman@google.com>
Aman Sanger <sangera@google.com>
Sarah Botwinick <sarahbot@google.com>
Legina Chen <legina@google.com>
Rachel Guan <rachelguan@google.com>
Juan Celhay <jicelhay@google.com>

View File

@@ -47,20 +47,9 @@ war {
if (project.path == ":services:default") {
war {
from("${coreResourcesDir}/google/registry/ui") {
include "registrar_bin.js"
if (environment != "production") {
include "registrar_bin.js.map"
}
into("assets/js")
}
from("${coreResourcesDir}/google/registry/ui/css") {
include "registrar*"
into("assets/css")
}
from("${coreResourcesDir}/google/registry/ui/assets/images") {
include "**/*"
into("assets/images")
from("${coreResourcesDir}/google/registry/ui/html") {
include "*.html"
into("registrar")
}
}
}
@@ -104,7 +93,6 @@ appengineDeployAll.finalizedBy ':deployCloudSchedulerAndQueue'
rootProject.deploy.dependsOn appengineDeployAll
rootProject.stage.dependsOn appengineStage
tasks['war'].dependsOn ':core:compileProdJS'
tasks['war'].dependsOn ':core:processResources'
tasks['war'].dependsOn ':core:jar'

View File

@@ -39,7 +39,7 @@ io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor,errorprone
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
jakarta.inject:jakarta.inject-api:1.0.5=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
javax.inject:javax.inject:1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
joda-time:joda-time:2.12.7=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
joda-time:joda-time:2.13.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
junit:junit:4.13.2=testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
net.sf.saxon:Saxon-HE:10.6=checkstyle
org.antlr:antlr4-runtime:4.9.3=checkstyle
@@ -55,11 +55,11 @@ org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
org.javassist:javassist:3.28.0-GA=checkstyle
org.jspecify:jspecify:0.3.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.junit.jupiter:junit-jupiter-api:5.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.11.0=testCompileClasspath,testRuntimeClasspath
org.junit:junit-bom:5.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.11.2=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.11.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.11.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.11.2=testCompileClasspath,testRuntimeClasspath
org.junit:junit-bom:5.11.2=testCompileClasspath,testRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:9.7=jacocoAnt
org.ow2.asm:asm-tree:9.7=jacocoAnt

View File

@@ -5075,9 +5075,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.16.4.tgz",
"integrity": "sha512-GkhjAaQ8oUTOKE4g4gsZ0u8K/IHU1+2WQSgS1TwTcYvL+sjbaQjNHFXbOJ6kgqGHIO1DfUhI/Sphi9GkRT9K+Q==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz",
"integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==",
"cpu": [
"arm"
],
@@ -5088,9 +5088,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.16.4.tgz",
"integrity": "sha512-Bvm6D+NPbGMQOcxvS1zUl8H7DWlywSXsphAeOnVeiZLQ+0J6Is8T7SrjGTH29KtYkiY9vld8ZnpV3G2EPbom+w==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz",
"integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==",
"cpu": [
"arm64"
],
@@ -5101,9 +5101,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.16.4.tgz",
"integrity": "sha512-i5d64MlnYBO9EkCOGe5vPR/EeDwjnKOGGdd7zKFhU5y8haKhQZTN2DgVtpODDMxUr4t2K90wTUJg7ilgND6bXw==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz",
"integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==",
"cpu": [
"arm64"
],
@@ -5114,9 +5114,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.16.4.tgz",
"integrity": "sha512-WZupV1+CdUYehaZqjaFTClJI72fjJEgTXdf4NbW69I9XyvdmztUExBtcI2yIIU6hJtYvtwS6pkTkHJz+k08mAQ==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz",
"integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==",
"cpu": [
"x64"
],
@@ -5127,9 +5127,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.16.4.tgz",
"integrity": "sha512-ADm/xt86JUnmAfA9mBqFcRp//RVRt1ohGOYF6yL+IFCYqOBNwy5lbEK05xTsEoJq+/tJzg8ICUtS82WinJRuIw==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz",
"integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==",
"cpu": [
"arm"
],
@@ -5140,9 +5140,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.16.4.tgz",
"integrity": "sha512-tJfJaXPiFAG+Jn3cutp7mCs1ePltuAgRqdDZrzb1aeE3TktWWJ+g7xK9SNlaSUFw6IU4QgOxAY4rA+wZUT5Wfg==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz",
"integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==",
"cpu": [
"arm"
],
@@ -5153,9 +5153,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.16.4.tgz",
"integrity": "sha512-7dy1BzQkgYlUTapDTvK997cgi0Orh5Iu7JlZVBy1MBURk7/HSbHkzRnXZa19ozy+wwD8/SlpJnOOckuNZtJR9w==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz",
"integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==",
"cpu": [
"arm64"
],
@@ -5166,9 +5166,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.16.4.tgz",
"integrity": "sha512-zsFwdUw5XLD1gQe0aoU2HVceI6NEW7q7m05wA46eUAyrkeNYExObfRFQcvA6zw8lfRc5BHtan3tBpo+kqEOxmg==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz",
"integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==",
"cpu": [
"arm64"
],
@@ -5179,9 +5179,9 @@
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.16.4.tgz",
"integrity": "sha512-p8C3NnxXooRdNrdv6dBmRTddEapfESEUflpICDNKXpHvTjRRq1J82CbU5G3XfebIZyI3B0s074JHMWD36qOW6w==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz",
"integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==",
"cpu": [
"ppc64"
],
@@ -5192,9 +5192,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.16.4.tgz",
"integrity": "sha512-Lh/8ckoar4s4Id2foY7jNgitTOUQczwMWNYi+Mjt0eQ9LKhr6sK477REqQkmy8YHY3Ca3A2JJVdXnfb3Rrwkng==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz",
"integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==",
"cpu": [
"riscv64"
],
@@ -5205,9 +5205,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.16.4.tgz",
"integrity": "sha512-1xwwn9ZCQYuqGmulGsTZoKrrn0z2fAur2ujE60QgyDpHmBbXbxLaQiEvzJWDrscRq43c8DnuHx3QorhMTZgisQ==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz",
"integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==",
"cpu": [
"s390x"
],
@@ -5218,9 +5218,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.16.4.tgz",
"integrity": "sha512-LuOGGKAJ7dfRtxVnO1i3qWc6N9sh0Em/8aZ3CezixSTM+E9Oq3OvTsvC4sm6wWjzpsIlOCnZjdluINKESflJLA==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz",
"integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==",
"cpu": [
"x64"
],
@@ -5231,9 +5231,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.16.4.tgz",
"integrity": "sha512-ch86i7KkJKkLybDP2AtySFTRi5fM3KXp0PnHocHuJMdZwu7BuyIKi35BE9guMlmTpwwBTB3ljHj9IQXnTCD0vA==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz",
"integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==",
"cpu": [
"x64"
],
@@ -5244,9 +5244,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.16.4.tgz",
"integrity": "sha512-Ma4PwyLfOWZWayfEsNQzTDBVW8PZ6TUUN1uFTBQbF2Chv/+sjenE86lpiEwj2FiviSmSZ4Ap4MaAfl1ciF4aSA==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz",
"integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==",
"cpu": [
"arm64"
],
@@ -5257,9 +5257,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.16.4.tgz",
"integrity": "sha512-9m/ZDrQsdo/c06uOlP3W9G2ENRVzgzbSXmXHT4hwVaDQhYcRpi9bgBT0FTG9OhESxwK0WjQxYOSfv40cU+T69w==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz",
"integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==",
"cpu": [
"ia32"
],
@@ -5270,9 +5270,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.16.4.tgz",
"integrity": "sha512-YunpoOAyGLDseanENHmbFvQSfVL5BxW3k7hhy0eN4rb3gS/ct75dVD0EXOWIqFT/nE8XYW6LP6vz6ctKRi0k9A==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz",
"integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==",
"cpu": [
"x64"
],
@@ -6625,9 +6625,9 @@
}
},
"node_modules/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"dev": true,
"dependencies": {
"bytes": "3.1.2",
@@ -6638,7 +6638,7 @@
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"qs": "6.13.0",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
@@ -7378,9 +7378,9 @@
"dev": true
},
"node_modules/cookie": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"dev": true,
"engines": {
"node": ">= 0.6"
@@ -8140,9 +8140,9 @@
}
},
"node_modules/engine.io": {
"version": "6.5.4",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz",
"integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==",
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz",
"integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==",
"dev": true,
"dependencies": {
"@types/cookie": "^0.4.1",
@@ -8150,25 +8150,46 @@
"@types/node": ">=10.0.0",
"accepts": "~1.3.4",
"base64id": "2.0.0",
"cookie": "~0.4.1",
"cookie": "~0.7.2",
"cors": "~2.8.5",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0"
"ws": "~8.17.1"
},
"engines": {
"node": ">=10.2.0"
}
},
"node_modules/engine.io-parser": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz",
"integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==",
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
"dev": true,
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/engine.io/node_modules/ws": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"dev": true,
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/enhanced-resolve": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz",
@@ -8819,37 +8840,37 @@
"dev": true
},
"node_modules/express": {
"version": "4.19.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
"dev": true,
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "1.20.2",
"body-parser": "1.20.3",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.6.0",
"cookie": "0.7.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~1.0.2",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.2.0",
"finalhandler": "1.3.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"merge-descriptors": "1.0.1",
"merge-descriptors": "1.0.3",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"path-to-regexp": "0.1.10",
"proxy-addr": "~2.0.7",
"qs": "6.11.0",
"qs": "6.13.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.18.0",
"serve-static": "1.15.0",
"send": "0.19.0",
"serve-static": "1.16.2",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "~1.6.18",
@@ -8861,9 +8882,9 @@
}
},
"node_modules/express/node_modules/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"dev": true,
"engines": {
"node": ">= 0.6"
@@ -8878,14 +8899,23 @@
"ms": "2.0.0"
}
},
"node_modules/express/node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
},
"node_modules/express/node_modules/finalhandler": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
"integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
"dev": true,
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
@@ -11420,10 +11450,13 @@
}
},
"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==",
"dev": true
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/merge-stream": {
"version": "2.0.0",
@@ -12431,10 +12464,13 @@
}
},
"node_modules/object-inspect": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
"integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -12897,9 +12933,9 @@
}
},
"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==",
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
"dev": true
},
"node_modules/path-type": {
@@ -13326,12 +13362,12 @@
}
},
"node_modules/qs": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dev": true,
"dependencies": {
"side-channel": "^1.0.4"
"side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
@@ -13663,9 +13699,9 @@
}
},
"node_modules/rollup": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.16.4.tgz",
"integrity": "sha512-kuaTJSUbz+Wsb2ATGvEknkI12XV40vIiHmLuFlejoo7HtDok/O5eDDD0UpCVY5bBX5U5RYo8wWP83H7ZsqVEnA==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz",
"integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==",
"dev": true,
"dependencies": {
"@types/estree": "1.0.5"
@@ -13678,22 +13714,22 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.16.4",
"@rollup/rollup-android-arm64": "4.16.4",
"@rollup/rollup-darwin-arm64": "4.16.4",
"@rollup/rollup-darwin-x64": "4.16.4",
"@rollup/rollup-linux-arm-gnueabihf": "4.16.4",
"@rollup/rollup-linux-arm-musleabihf": "4.16.4",
"@rollup/rollup-linux-arm64-gnu": "4.16.4",
"@rollup/rollup-linux-arm64-musl": "4.16.4",
"@rollup/rollup-linux-powerpc64le-gnu": "4.16.4",
"@rollup/rollup-linux-riscv64-gnu": "4.16.4",
"@rollup/rollup-linux-s390x-gnu": "4.16.4",
"@rollup/rollup-linux-x64-gnu": "4.16.4",
"@rollup/rollup-linux-x64-musl": "4.16.4",
"@rollup/rollup-win32-arm64-msvc": "4.16.4",
"@rollup/rollup-win32-ia32-msvc": "4.16.4",
"@rollup/rollup-win32-x64-msvc": "4.16.4",
"@rollup/rollup-android-arm-eabi": "4.22.4",
"@rollup/rollup-android-arm64": "4.22.4",
"@rollup/rollup-darwin-arm64": "4.22.4",
"@rollup/rollup-darwin-x64": "4.22.4",
"@rollup/rollup-linux-arm-gnueabihf": "4.22.4",
"@rollup/rollup-linux-arm-musleabihf": "4.22.4",
"@rollup/rollup-linux-arm64-gnu": "4.22.4",
"@rollup/rollup-linux-arm64-musl": "4.22.4",
"@rollup/rollup-linux-powerpc64le-gnu": "4.22.4",
"@rollup/rollup-linux-riscv64-gnu": "4.22.4",
"@rollup/rollup-linux-s390x-gnu": "4.22.4",
"@rollup/rollup-linux-x64-gnu": "4.22.4",
"@rollup/rollup-linux-x64-musl": "4.22.4",
"@rollup/rollup-win32-arm64-msvc": "4.22.4",
"@rollup/rollup-win32-ia32-msvc": "4.22.4",
"@rollup/rollup-win32-x64-msvc": "4.22.4",
"fsevents": "~2.3.2"
}
},
@@ -13916,9 +13952,9 @@
"dev": true
},
"node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"dev": true,
"dependencies": {
"debug": "2.6.9",
@@ -14060,20 +14096,29 @@
"dev": true
},
"node_modules/serve-static": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
"version": "1.16.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
"integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
"dev": true,
"dependencies": {
"encodeurl": "~1.0.2",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
"send": "0.18.0"
"send": "0.19.0"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/serve-static/node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -14200,16 +14245,16 @@
}
},
"node_modules/socket.io": {
"version": "4.7.5",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz",
"integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==",
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz",
"integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==",
"dev": true,
"dependencies": {
"accepts": "~1.3.4",
"base64id": "~2.0.0",
"cors": "~2.8.5",
"debug": "~4.3.2",
"engine.io": "~6.5.2",
"engine.io": "~6.6.0",
"socket.io-adapter": "~2.5.2",
"socket.io-parser": "~4.2.4"
},

View File

@@ -18,15 +18,12 @@ import { BillingInfoComponent } from './billingInfo/billingInfo.component';
import { DomainListComponent } from './domains/domainList.component';
import { HomeComponent } from './home/home.component';
import { RegistryLockVerifyComponent } from './lock/registryLockVerify.component';
import { NewOteComponent } from './ote/newOte.component';
import { OteStatusComponent } from './ote/oteStatus.component';
import { RegistrarDetailsComponent } from './registrar/registrarDetails.component';
import { RegistrarComponent } from './registrar/registrarsTable.component';
import { ResourcesComponent } from './resources/resources.component';
import ContactComponent from './settings/contact/contact.component';
import SecurityComponent from './settings/security/security.component';
import { SettingsComponent } from './settings/settings.component';
import UsersComponent from './settings/users/users.component';
import WhoisComponent from './settings/whois/whois.component';
import { SupportComponent } from './support/support.component';
@@ -37,6 +34,7 @@ export interface RouteWithIcon extends Route {
export const PATHS = {
NewOteComponent: 'new-ote',
OteStatusComponent: 'ote-status/:registrarId',
UsersComponent: 'users',
};
export const routes: RouteWithIcon[] = [
{ path: '', redirectTo: '/home', pathMatch: 'full' },
@@ -94,10 +92,6 @@ export const routes: RouteWithIcon[] = [
component: SecurityComponent,
title: 'Security',
},
{
path: UsersComponent.PATH,
component: UsersComponent,
},
],
},
// {
@@ -128,6 +122,13 @@ export const routes: RouteWithIcon[] = [
title: 'Resources',
iconName: 'description',
},
{
path: PATHS.UsersComponent,
title: 'Users',
iconName: 'manage_accounts',
loadComponent: () =>
import('./users/users.component').then((mod) => mod.UsersComponent),
},
{
path: SupportComponent.PATH,
component: SupportComponent,

View File

@@ -32,8 +32,6 @@ import { HeaderComponent } from './header/header.component';
import { HomeComponent } from './home/home.component';
import { RegistryLockVerifyComponent } from './lock/registryLockVerify.component';
import { NavigationComponent } from './navigation/navigation.component';
import { NewOteComponent } from './ote/newOte.component';
import { OteStatusComponent } from './ote/oteStatus.component';
import NewRegistrarComponent from './registrar/newRegistrar.component';
import { RegistrarDetailsComponent } from './registrar/registrarDetails.component';
import { RegistrarSelectorComponent } from './registrar/registrarSelector.component';
@@ -58,6 +56,14 @@ import { SnackBarModule } from './snackbar.module';
import { SupportComponent } from './support/support.component';
import { TldsComponent } from './tlds/tlds.component';
@NgModule({
declarations: [SelectedRegistrarWrapper],
imports: [MaterialModule],
exports: [SelectedRegistrarWrapper],
providers: [],
})
export class SelectedRegistrarModule {}
@NgModule({
declarations: [
AppComponent,
@@ -80,7 +86,6 @@ import { TldsComponent } from './tlds/tlds.component';
ResourcesComponent,
SecurityComponent,
SecurityEditComponent,
SelectedRegistrarWrapper,
SettingsComponent,
SettingsContactComponent,
SupportComponent,
@@ -96,8 +101,8 @@ import { TldsComponent } from './tlds/tlds.component';
FormsModule,
MaterialModule,
SnackBarModule,
SelectedRegistrarModule,
],
exports: [SelectedRegistrarWrapper],
providers: [
BackendService,
BreakPointObserverService,

View File

@@ -95,9 +95,9 @@
<ng-container matColumnDef="statuses">
<mat-header-cell *matHeaderCellDef>Statuses</mat-header-cell>
<mat-cell *matCellDef="let element">{{
element.statuses
}}</mat-cell>
<mat-cell *matCellDef="let element">
<span>{{ element.statuses?.join(", ") }}</span>
</mat-cell>
</ng-container>
<ng-container matColumnDef="registryLock">

View File

@@ -36,6 +36,11 @@
.mat-column-registryLock {
max-width: 150px;
}
.mat-column-statuses span {
padding: 10px 0;
overflow: hidden;
word-break: break-word;
}
}
&__domains-spinner {

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { HttpErrorResponse } from '@angular/common/http';
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
import { Component, ViewChild, effect } from '@angular/core';
import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { MatSnackBar } from '@angular/material/snack-bar';
@@ -91,7 +91,10 @@ export class DomainListComponent {
loadLocks() {
this.registryLockService.retrieveLocks().subscribe({
error: (err: HttpErrorResponse) => {
this._snackBar.open(err.message);
if (err.status !== HttpStatusCode.Forbidden) {
// Some users may not have registry lock permissions and that's OK
this._snackBar.open(err.message);
}
},
});
}

View File

@@ -17,8 +17,9 @@ import { Component } from '@angular/core';
import { MatTreeNestedDataSource } from '@angular/material/tree';
import { NavigationEnd, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { RouteWithIcon, routes } from '../app-routing.module';
import { RouteWithIcon, routes, PATHS } from '../app-routing.module';
import { RESTRICTED_ELEMENTS } from '../shared/directives/userLevelVisiblity.directive';
import { RegistrarComponent } from '../registrar/registrarsTable.component';
interface NavMenuNode extends RouteWithIcon {
parentRoute?: RouteWithIcon;
@@ -59,9 +60,12 @@ export class NavigationComponent {
}
getElementId(node: RouteWithIcon) {
return node.path === 'registrars'
? RESTRICTED_ELEMENTS.REGISTRAR_ELEMENT
: null;
if (node.path === RegistrarComponent.PATH) {
return RESTRICTED_ELEMENTS.REGISTRAR_ELEMENT;
} else if (node.path === PATHS.UsersComponent) {
return RESTRICTED_ELEMENTS.USERS;
}
return null;
}
syncExpandedNavigationWithRoute(url: string) {

View File

@@ -13,7 +13,7 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { switchMap } from 'rxjs';
import { switchMap, timeout } from 'rxjs';
import {
IpAllowListItem,
RegistrarService,
@@ -69,6 +69,7 @@ export class SecurityService {
uiToApiConverter(newSecuritySettings)
)
.pipe(
timeout(2000),
switchMap(() => {
return this.registrarService.loadRegistrars();
})

View File

@@ -10,6 +10,7 @@
<mat-form-field appearance="outline">
<input
matInput
[disabled]="isUpdating"
type="text"
[(ngModel)]="ip.value"
[ngModelOptions]="{ standalone: true }"
@@ -20,12 +21,19 @@
mat-icon-button
aria-label="Remove"
(click)="removeIpEntry(ip)"
[disabled]="isUpdating"
>
<mat-icon>close</mat-icon>
</button>
</div>
}
<button mat-button color="primary" (click)="createIpEntry()" type="button">
<button
mat-button
[disabled]="isUpdating"
color="primary"
(click)="createIpEntry()"
type="button"
>
+ Add IP
</button>
@@ -35,6 +43,7 @@
<textarea
class="console-app__clientCertificateValue"
matInput
[disabled]="isUpdating"
[(ngModel)]="dataSource.clientCertificate"
[ngModelOptions]="{ standalone: true }"
></textarea>
@@ -44,6 +53,7 @@
<mat-form-field appearance="outline">
<textarea
matInput
[disabled]="isUpdating"
[(ngModel)]="dataSource.failoverClientCertificate"
[ngModelOptions]="{ standalone: true }"
></textarea>
@@ -51,6 +61,7 @@
<button
mat-flat-button
color="primary"
[disabled]="isUpdating"
aria-label="Save security settings"
type="submit"
class="settings-security__edit-save"

View File

@@ -29,6 +29,7 @@ import { SecurityService, apiToUiConverter } from './security.service';
})
export default class SecurityEditComponent {
dataSource: SecuritySettings = {};
isUpdating = false;
constructor(
public securityService: SecurityService,
@@ -43,12 +44,15 @@ export default class SecurityEditComponent {
}
save() {
this.isUpdating = true;
this.securityService.saveChanges(this.dataSource).subscribe({
complete: () => {
this.isUpdating = false;
this.goBack();
},
error: (err: HttpErrorResponse) => {
this._snackBar.open(err.error);
this._snackBar.open(err.error || err.message);
this.isUpdating = false;
},
});
}

View File

@@ -1 +0,0 @@
<p>users works!</p>

View File

@@ -1,36 +0,0 @@
// 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.
import { ComponentFixture, TestBed } from '@angular/core/testing';
import UsersComponent from './users.component';
describe('UsersComponent', () => {
let component: UsersComponent;
let fixture: ComponentFixture<UsersComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [UsersComponent],
}).compileComponents();
fixture = TestBed.createComponent(UsersComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -18,10 +18,17 @@ import { UserDataService } from '../services/userData.service';
export enum RESTRICTED_ELEMENTS {
REGISTRAR_ELEMENT,
OTE,
USERS,
}
export const DISABLED_ELEMENTS_PER_ROLE = {
NONE: [RESTRICTED_ELEMENTS.REGISTRAR_ELEMENT, RESTRICTED_ELEMENTS.OTE],
NONE: [
RESTRICTED_ELEMENTS.REGISTRAR_ELEMENT,
RESTRICTED_ELEMENTS.OTE,
RESTRICTED_ELEMENTS.USERS,
],
SUPPORT_LEAD: [RESTRICTED_ELEMENTS.USERS],
SUPPORT_AGENT: [RESTRICTED_ELEMENTS.USERS],
};
@Directive({

View File

@@ -21,6 +21,7 @@ import { DomainLocksResult } from 'src/app/domains/registryLock.service';
import { RegistryLockVerificationResponse } from 'src/app/lock/registryLockVerify.service';
import { OteCreateResponse } from 'src/app/ote/newOte.component';
import { OteStatusResponse } from 'src/app/ote/oteStatus.component';
import { User } from 'src/app/users/users.service';
import {
Registrar,
SecuritySettingsBackendModel,
@@ -159,6 +160,32 @@ export class BackendService {
);
}
getUsers(registrarId: string): Observable<User[]> {
return this.http
.get<User[]>(`/console-api/users?registrarId=${registrarId}`)
.pipe(catchError((err) => this.errorCatcher<User[]>(err)));
}
createUser(registrarId: string): Observable<User> {
return this.http
.post<User>(`/console-api/users?registrarId=${registrarId}`, {})
.pipe(catchError((err) => this.errorCatcher<User>(err)));
}
deleteUser(registrarId: string, user: User): Observable<any> {
return this.http
.delete<any>(`/console-api/users?registrarId=${registrarId}`, {
body: JSON.stringify(user),
})
.pipe(catchError((err) => this.errorCatcher<any>(err)));
}
updateUser(registrarId: string, updatedUser: User): Observable<any> {
return this.http
.put<User>(`/console-api/users?registrarId=${registrarId}`, updatedUser)
.pipe(catchError((err) => this.errorCatcher<any>(err)));
}
getUserData(): Observable<UserData> {
return this.http
.get<UserData>('/console-api/userdata')

View File

@@ -0,0 +1,125 @@
<div class="console-app__user-details">
@if(isEditing) {
<h1 class="mat-headline-4">Editing {{ userDetails().emailAddress }}</h1>
<mat-divider></mat-divider>
<div class="console-app__user-details-controls">
<button
mat-icon-button
aria-label="Back to view user"
(click)="isEditing = false"
>
<mat-icon>arrow_back</mat-icon>
</button>
</div>
<form (ngSubmit)="saveEdit()">
<p>
<mat-form-field appearance="outline">
<mat-label
>User Role:
<mat-icon
matTooltip="Viewer role doesn't allow making updates; Editor role allows updates, like Contacts delete or SSL certificate change"
>help_outline</mat-icon
></mat-label
>
<mat-select [(ngModel)]="userRole" name="userRole">
<mat-option value="PRIMARY_CONTACT">Editor</mat-option>
<mat-option value="ACCOUNT_MANAGER">Viewer</mat-option>
</mat-select>
</mat-form-field>
</p>
<button
mat-flat-button
color="primary"
aria-label="Save user"
type="submit"
>
Save
</button>
</form>
} @else { @if(isNewUser) {
<h1 class="mat-headline-4">
{{ userDetails().emailAddress + " successfully created" }}
</h1>
} @else {
<h1 class="mat-headline-4">User details</h1>
<mat-divider></mat-divider>
<div class="console-app__user-details-controls">
<button mat-icon-button aria-label="Back to users list" (click)="goBack()">
<mat-icon>arrow_back</mat-icon>
</button>
<div class="spacer"></div>
<button
mat-flat-button
color="primary"
aria-label="Edit User"
(click)="userRole = userDetails().role; isEditing = true"
>
<mat-icon>edit</mat-icon>
Edit
</button>
<button
mat-icon-button
aria-label="Delete User"
(click)="deleteUser()"
[disabled]="isLoading"
>
<mat-icon>delete</mat-icon>
</button>
</div>
<div *ngIf="isNewUser" class="console-app__user-details-save-password">
<mat-icon>priority_high</mat-icon>
Please save the password. For your security, we do not store passwords in a
recoverable format.
</div>
<p *ngIf="isLoading">
<mat-progress-bar mode="query"></mat-progress-bar>
</p>
<mat-card appearance="outlined">
<mat-card-content>
<mat-list role="list">
<mat-list-item role="listitem">
<h2>User details</h2>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item role="listitem">
<span class="console-app__list-key">User email</span>
<span class="console-app__list-value">{{
userDetails().emailAddress
}}</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item role="listitem">
<span class="console-app__list-key">User role</span>
<span class="console-app__list-value">{{
roleToDescription(userDetails().role)
}}</span>
</mat-list-item>
@if (userDetails().password) {
<mat-divider></mat-divider>
<mat-list-item role="listitem">
<span class="console-app__list-key">Password</span>
<span
class="console-app__list-value console-app__user-details-password"
>
<input
[type]="isPasswordVisible ? 'text' : 'password'"
[value]="userDetails().password"
disabled
/>
<button
mat-button
aria-label="Show password"
(click)="isPasswordVisible = !isPasswordVisible"
>
{{ isPasswordVisible ? "Hide" : "View" }} password
</button>
</span>
</mat-list-item>
}
</mat-list>
</mat-card-content>
</mat-card>
}}
</div>

View File

@@ -11,3 +11,29 @@
// 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.
.console-app {
&__user-details {
&-controls {
display: flex;
align-items: center;
margin: 20px 0;
}
&-password {
input {
border: none;
background: transparent;
}
}
&-save-password {
display: flex;
justify-content: center;
align-items: center;
padding: 15px 10px;
margin-bottom: 20px;
border: 1px solid #ddd;
border-radius: 10px;
}
max-width: 616px;
}
}

View File

@@ -0,0 +1,105 @@
// 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.
import { CommonModule } from '@angular/common';
import { Component, computed } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { SelectedRegistrarModule } from '../app.module';
import { MaterialModule } from '../material.module';
import { RegistrarService } from '../registrar/registrar.service';
import { SnackBarModule } from '../snackbar.module';
import { User, UsersService, roleToDescription } from './users.service';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-user-edit',
templateUrl: './userEdit.component.html',
styleUrls: ['./userEdit.component.scss'],
standalone: true,
imports: [
FormsModule,
MaterialModule,
SnackBarModule,
CommonModule,
SelectedRegistrarModule,
],
providers: [],
})
export class UserEditComponent {
isEditing = false;
isPasswordVisible = false;
isNewUser = false;
isLoading = false;
userRole = '';
userDetails = computed(() => {
return this.usersService
.users()
.filter(
(u) => u.emailAddress === this.usersService.currentlyOpenUserEmail()
)[0];
});
constructor(
protected registrarService: RegistrarService,
protected usersService: UsersService,
private _snackBar: MatSnackBar
) {
if (this.usersService.isNewUser) {
this.isNewUser = true;
this.usersService.isNewUser = false;
}
}
roleToDescription(role: string) {
return roleToDescription(role);
}
deleteUser() {
this.isLoading = true;
this.usersService.deleteUser(this.userDetails()).subscribe({
error: (err) => {
this._snackBar.open(err.error || err.message);
this.isLoading = false;
},
complete: () => {
this.isLoading = false;
this.goBack();
},
});
}
goBack() {
this.usersService.currentlyOpenUserEmail.set('');
}
saveEdit() {
this.isLoading = true;
this.usersService
.updateUser({
role: this.userRole,
emailAddress: this.userDetails().emailAddress,
})
.subscribe({
error: (err) => {
this._snackBar.open(err.error || err.message);
this.isLoading = false;
},
complete: () => {
this.isLoading = false;
this.isEditing = false;
},
});
}
}

View File

@@ -0,0 +1,48 @@
<app-selected-registrar-wrapper>
@if(isLoading) {
<div class="console-app__users-spinner">
<mat-spinner />
</div>
} @else if(usersService.currentlyOpenUserEmail()) {
<app-user-edit></app-user-edit>
} @else {
<div class="console-app__users">
<div class="console-app__users-header">
<h1 class="mat-headline-4">Users</h1>
<div class="spacer"></div>
<button
mat-flat-button
(click)="createNewUser()"
aria-label="Create new user"
color="primary"
>
Create a Viewer User
</button>
</div>
<mat-table
[dataSource]="dataSource"
class="mat-elevation-z0"
class="console-app__users-table"
matSort
>
<ng-container
*ngFor="let column of columns"
[matColumnDef]="column.columnDef"
>
<mat-header-cell *matHeaderCellDef>
{{ column.header }}
</mat-header-cell>
<mat-cell
*matCellDef="let row"
[innerHTML]="column.cell(row)"
></mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row
*matRowDef="let row; columns: displayedColumns"
(click)="openDetails(row.emailAddress)"
></mat-row>
</mat-table>
</div>
}
</app-selected-registrar-wrapper>

View File

@@ -12,13 +12,27 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component } from '@angular/core';
.console-app {
&__users-spinner {
align-items: center;
display: flex;
justify-content: center;
}
@Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.scss'],
})
export default class UsersComponent {
public static PATH = 'users';
$min-width: 756px;
$max-width: 1024px;
&__users-table {
min-width: $min-width !important;
max-width: $max-width;
}
&__users-new {
margin-left: 20px;
}
&__users-header {
display: flex;
justify-content: space-between;
}
}

View File

@@ -0,0 +1,113 @@
// 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.
import { CommonModule } from '@angular/common';
import { HttpErrorResponse } from '@angular/common/http';
import { Component, effect, ViewChild } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { SelectedRegistrarModule } from '../app.module';
import { MaterialModule } from '../material.module';
import { RegistrarService } from '../registrar/registrar.service';
import { SnackBarModule } from '../snackbar.module';
import { UserEditComponent } from './userEdit.component';
import { roleToDescription, User, UsersService } from './users.service';
export const columns = [
{
columnDef: 'emailAddress',
header: 'User email',
cell: (record: User) => `${record.emailAddress || ''}`,
},
{
columnDef: 'role',
header: 'User role',
cell: (record: User) => `${roleToDescription(record.role)}`,
},
];
@Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.scss'],
standalone: true,
imports: [
MaterialModule,
SnackBarModule,
CommonModule,
SelectedRegistrarModule,
UserEditComponent,
],
providers: [UsersService],
})
export class UsersComponent {
dataSource: MatTableDataSource<User>;
columns = columns;
displayedColumns = this.columns.map((c) => c.columnDef);
isLoading = false;
@ViewChild(MatSort) sort!: MatSort;
constructor(
protected registrarService: RegistrarService,
protected usersService: UsersService,
private _snackBar: MatSnackBar
) {
this.dataSource = new MatTableDataSource<User>(usersService.users());
effect(() => {
if (registrarService.registrarId()) {
this.loadUsers();
}
});
effect(() => {
this.dataSource.data = usersService.users();
});
}
ngAfterViewInit() {
this.dataSource.sort = this.sort;
}
loadUsers() {
this.isLoading = true;
this.usersService.fetchUsers().subscribe({
error: (err: HttpErrorResponse) => {
this._snackBar.open(err.error || err.message);
this.isLoading = false;
},
complete: () => {
this.isLoading = false;
},
});
}
createNewUser() {
this.isLoading = true;
this.usersService.createNewUser().subscribe({
error: (err: HttpErrorResponse) => {
this._snackBar.open(err.error || err.message);
this.isLoading = false;
},
complete: () => {
this.isLoading = false;
},
});
}
openDetails(emailAddress: string) {
this.usersService.currentlyOpenUserEmail.set(emailAddress);
}
}

View File

@@ -0,0 +1,82 @@
// 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.
import { Injectable, signal } from '@angular/core';
import { switchMap, tap } from 'rxjs';
import { RegistrarService } from '../registrar/registrar.service';
import { BackendService } from '../shared/services/backend.service';
export const roleToDescription = (role: string) => {
if (!role) return 'N/A';
else if (role === 'ACCOUNT_MANAGER') {
return 'Viewer';
}
return 'Editor';
};
export interface CreateAutoTimestamp {
creationTime: string;
}
export interface User {
emailAddress: string;
role: string;
password?: string;
}
@Injectable()
export class UsersService {
users = signal<User[]>([]);
currentlyOpenUserEmail = signal<string>('');
isNewUser: boolean = false;
constructor(
private backendService: BackendService,
private registrarService: RegistrarService
) {}
fetchUsers() {
return this.backendService
.getUsers(this.registrarService.registrarId())
.pipe(
tap((users: User[]) => {
this.users.set(users);
})
);
}
createNewUser() {
return this.backendService
.createUser(this.registrarService.registrarId())
.pipe(
tap((newUser: User) => {
this.users.set([...this.users(), newUser]);
this.currentlyOpenUserEmail.set(newUser.emailAddress);
this.isNewUser = true;
})
);
}
deleteUser(user: User) {
return this.backendService
.deleteUser(this.registrarService.registrarId(), user)
.pipe(switchMap((_) => this.fetchUsers()));
}
updateUser(updatedUser: User) {
return this.backendService
.updateUser(this.registrarService.registrarId(), updatedUser)
.pipe(switchMap((_) => this.fetchUsers()));
}
}

View File

@@ -98,10 +98,8 @@ processTestResources {
}
configurations {
css
jaxb
soy
closureCompiler
devtool
nonprodImplementation.extendsFrom implementation
@@ -120,8 +118,6 @@ configurations {
all {
// servlet-api:3.1 pulled in but not used by soy compiler
exclude group: 'javax.servlet', module: 'javax.servlet-api'
// Jetty's servlet-api:2.5 implementation, pulled in by other Jetty jars
exclude group: 'org.mortbay.jetty', module: 'servlet-api'
}
}
@@ -179,7 +175,6 @@ dependencies {
implementation deps['com.google.oauth-client:google-oauth-client-java6']
implementation deps['com.google.oauth-client:google-oauth-client-jetty']
implementation deps['com.google.oauth-client:google-oauth-client-servlet']
implementation deps['com.google.protobuf:protobuf-java']
implementation deps['com.google.re2j:re2j']
implementation deps['com.google.template:soy']
implementation deps['com.googlecode.json-simple:json-simple']
@@ -293,27 +288,20 @@ dependencies {
// Dependencies needed for jaxb compilation.
jaxb deps['jakarta.xml.bind:jakarta.xml.bind-api']
jaxb deps['com.sun.xml.bind:jaxb-xjc']
jaxb deps['com.sun.xml.bind:jaxb-impl']
jaxb deps['com.sun.xml.bind:jaxb-osgi']
jaxb deps['org.glassfish.jaxb:jaxb-runtime']
jaxb deps['org.glassfish.jaxb:jaxb-xjc']
// Dependency needed for soy to java compilation.
soy deps['com.google.inject:guice']
soy deps['com.google.protobuf:protobuf-java']
// Read dependencies.gradle on why the protobuf version is pinned directly.
soy 'com.google.protobuf:protobuf-java:[3.25.5, 4.0.0)!!'
soy deps['com.google.template:soy']
// Dependencies needed for compiling stylesheets to javascript
css deps['com.google.closure-stylesheets:closure-stylesheets']
css deps['args4j:args4j']
// Tool dependencies. used for doc generation.
implementation files("${System.properties['java.home']}/../lib/tools.jar")
// Flyway classes needed to generate the golden file.
implementation deps['org.flywaydb:flyway-core']
implementation deps['org.flywaydb:flyway-database-postgresql']
closureCompiler deps['com.google.javascript:closure-compiler']
}
task jaxbToJava {
@@ -384,9 +372,8 @@ task soyToJava {
// Relative paths of soy directories.
def spec11SoyDir = "google/registry/reporting/spec11/soy"
def toolsSoyDir = "google/registry/tools/soy"
def registrarSoyDir = "google/registry/ui/soy/registrar"
def soyRelativeDirs = [spec11SoyDir, toolsSoyDir, registrarSoyDir]
def soyRelativeDirs = [spec11SoyDir, toolsSoyDir]
soyRelativeDirs.each {
inputs.dir "${resourcesSourceDir}/${it}"
outputs.dir "${generatedDir}/${it}"
@@ -399,9 +386,7 @@ task soyToJava {
args "--javaPackage", "${javaPackage}",
"--outputDirectory", "${outputDirectory}",
"--javaClassNameSource", "filename",
"--allowExternalCalls", "true",
"--srcs", "${soyFiles.join(',')}",
"--compileTimeGlobalsFile", "${resourcesSourceDir}/google/registry/ui/globals.txt"
"--srcs", "${soyFiles.join(',')}"
}
// Replace the "@link" tags after the "@deprecated" tags in the generated
@@ -428,12 +413,6 @@ task soyToJava {
dir: "${resourcesSourceDir}/${toolsSoyDir}",
include: ['**/*.soy']))
soyToJava('google.registry.ui.soy.registrar',
"${generatedDir}/${registrarSoyDir}",
fileTree(
dir: "${resourcesSourceDir}/${registrarSoyDir}",
include: ['**/*.soy']))
soyToJava('google.registry.reporting.spec11.soy',
"${generatedDir}/${spec11SoyDir}",
fileTree(
@@ -442,134 +421,8 @@ task soyToJava {
}
}
task soyToJS(type: JavaExec) {
def rootSoyDirectory = "${resourcesSourceDir}/google/registry/ui/soy/registrar"
def outputSoyDirectory = "${generatedDir}/google/registry/ui/soy/registrar"
inputs.dir rootSoyDirectory
outputs.dir outputSoyDirectory
def inputSoyFiles = files {
file("${rootSoyDirectory}").listFiles()
}.filter {
it.name.endsWith(".soy")
}
classpath configurations.soy
main = "com.google.template.soy.SoyToJsSrcCompiler"
args "--outputPathFormat", "${outputSoyDirectory}/{INPUT_FILE_NAME}.js",
"--allowExternalCalls", "false",
"--srcs", "${inputSoyFiles.join(',')}",
"--compileTimeGlobalsFile", "${resourcesSourceDir}/google/registry/ui/globals.txt"
}
task stylesheetsToJavascript {
def cssSourceDir = "${jsDir}/google/registry/ui/css"
def outputDir = "${resourcesDir}/google/registry/ui/css"
inputs.dir cssSourceDir
outputs.dir outputDir
ext.cssCompile = { outputName, debug, cssFiles ->
javaexec {
main = "com.google.common.css.compiler.commandline.ClosureCommandLineCompiler"
classpath configurations.css
def argsBuffer = [
"--output-file", "${outputName}.css",
"--output-source-map", "${outputName}.css.map",
"--input-orientation", "LTR",
"--output-orientation", "NOCHANGE",
"--output-renaming-map", "${outputName}.css.js",
"--output-renaming-map-format", "CLOSURE_COMPILED_SPLIT_HYPHENS"
]
if (debug) {
argsBuffer.addAll(["--rename", "DEBUG", "--pretty-print"])
} else {
argsBuffer.addAll(["--rename", "CLOSURE"])
}
argsBuffer.addAll(cssFiles)
args argsBuffer
}
}
doLast {
file("${outputDir}").mkdirs()
def ignoredFiles = ["demo_css.css", "registrar_imports_raw.css"]
def sourceFiles = []
// include all CSS files that we find except for the ones explicitly ignored
fileTree(cssSourceDir).each {
if (it.name.endsWith(".css") && !ignoredFiles.contains(it.name)) {
sourceFiles << (cssSourceDir + "/" + it.name)
}
}
// The css files have to be passed to the compiler in alphabetic order to
// avoid some flaky style issues
sourceFiles.sort()
cssCompile("${outputDir}/registrar_bin", false, sourceFiles)
cssCompile("${outputDir}/registrar_dbg", true, sourceFiles)
}
}
task compileProdJS(type: JavaExec) {
def outputDir = "${resourcesDir}/google/registry/ui"
def nodeModulesDir = "${rootDir}/node_modules"
def cssSourceDir = "${resourcesDir}/google/registry/ui/css"
def jsSourceDir = "${jsDir}/google/registry/ui/js"
def externsDir = "${jsDir}/google/registry/ui/externs"
def soySourceDir = "${generatedDir}/google/registry/ui/soy"
[nodeModulesDir, cssSourceDir, jsSourceDir, externsDir, soySourceDir].each {
inputs.dir "${it}"
}
outputs.dir outputDir
classpath configurations.closureCompiler
main = 'com.google.javascript.jscomp.CommandLineRunner'
def closureArgs = []
closureArgs << "--js_output_file=${outputDir}/registrar_bin.js"
// sourcemap-related configuration
closureArgs << "--create_source_map=${outputDir}/registrar_bin.js.map"
closureArgs << "--source_map_include_content=true"
closureArgs << "--source_map_location_mapping=${rootDir}/|"
closureArgs << "--output_wrapper=\"%output% //# sourceMappingURL=registrar_bin.js.map\""
// compilation options
closureArgs << "--compilation_level=ADVANCED"
closureArgs << "--entry_point=goog:registry.registrar.main"
closureArgs << "--generate_exports"
// manually include all the required js files
closureArgs << "--js=${nodeModulesDir}/google-closure-library/**/*.js"
closureArgs << "--js=${jsDir}/*.js"
closureArgs << "--js=${cssSourceDir}/registrar_bin.css.js"
closureArgs << "--js=${jsSourceDir}/**.js"
closureArgs << "--js=${externsDir}/json.js"
closureArgs << "--js=${soySourceDir}/**.js"
args closureArgs
}
compileProdJS.dependsOn soyToJava
compileJava.dependsOn jaxbToJava
compileJava.dependsOn soyToJava
// The Closure JS compiler does not support Windows. It is fine to disable it if
// all we want to do is to complile the Java code on Windows.
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
compileJava.dependsOn compileProdJS
assemble.dependsOn compileProdJS
}
// stylesheetsToJavascript must happen after processResources, which wipes the
// resources folder before copying data into it.
stylesheetsToJavascript.dependsOn processResources
classes.dependsOn stylesheetsToJavascript
compileProdJS.dependsOn stylesheetsToJavascript
compileProdJS.dependsOn rootProject.npmInstall
compileProdJS.dependsOn processResources
compileProdJS.dependsOn processTestResources
compileProdJS.dependsOn soyToJS
// Make testing artifacts available to be depended up on by other projects.
// TODO: factor out google.registry.testing to be a separate project.
@@ -830,16 +683,7 @@ artifacts {
devtool devtool
}
task copyJsFilesForTestServer(dependsOn: assemble, type: Copy) {
// Unfortunately the test server relies on having some compiled JS/CSS
// in place, so copy it over here
from "${resourcesDir}/google/registry/ui/"
include '**/*.js'
include '**/*.css'
into "${project.projectDir}/src/main/resources/google/registry/ui/"
}
task runTestServer(dependsOn: copyJsFilesForTestServer, type: JavaExec) {
task runTestServer(type: JavaExec) {
main = 'google.registry.server.RegistryTestServerMain'
classpath = sourceSets.test.runtimeClasspath
}
@@ -911,6 +755,9 @@ task fragileTest(type: FilteringTest) {
// Common exclude pattern. See README in parent directory for explanation.
tests = fragileTestPatterns
// Screenshot tests depend on the console being built
dependsOn(rootProject.project('console-webapp').tasks.named('buildConsoleWebapp'))
if (rootProject.findProperty("skipDockerIncompatibleTests") == "true") {
exclude dockerIncompatibleTestPatterns
}

View File

@@ -2,19 +2,16 @@
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
aopalliance:aopalliance:1.0=annotationProcessor,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
args4j:args4j:2.0.23=soy
args4j:args4j:2.0.26=css
args4j:args4j:2.33=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
cglib:cglib-nodep:2.2=css
args4j:args4j:2.33=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.charleskorn.kaml:kaml:0.20.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-annotations:2.18.0-rc1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-core:2.18.0-rc1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-databind:2.18.0-rc1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.18.0-rc1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.0-rc1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.18.0-rc1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.0-rc1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.18.0-rc1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-annotations:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-core:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-databind:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml:classmate:1.5.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:3.1.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -38,7 +35,7 @@ com.google.api-client:google-api-client-servlet:2.2.0=testRuntimeClasspath
com.google.api-client:google-api-client-servlet:2.7.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.api-client:google-api-client:2.7.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.32.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.42.0-alpha=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.43.2-beta=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.5.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.177.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.177.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -49,8 +46,8 @@ com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.66.0=compileCl
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.32.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.42.0-alpha=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-common-protos:2.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.43.2-beta=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-common-protos:2.39.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.5.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.177.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.177.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -62,47 +59,46 @@ com.google.api.grpc:proto-google-cloud-monitoring-v3:3.44.0=compileClasspath,dep
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.111.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.13.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.29.0=testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.48.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:2.29.0=testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.48.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-executor-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.32.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.42.0-alpha=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.43.2-beta=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2:2.29.0=testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2:2.48.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.119.0=testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.138.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.142.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.119.0=testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.138.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.api.grpc:proto-google-common-protos:2.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.38.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:api-common:2.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax-grpc:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax-httpjson:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-admin-directory:directory_v1-rev20240903-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-bigquery:v2-rev20240815-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.142.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.api.grpc:proto-google-common-protos:2.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:api-common:2.38.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax-grpc:2.55.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax-httpjson:2.55.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax:2.55.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-admin-directory:directory_v1-rev20240924-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-bigquery:v2-rev20240919-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20240310-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dataflow:v1b3-rev20240817-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dns:v1-rev20240719-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-drive:v3-rev20240903-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-drive:v3-rev20240914-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-gmail:v1-rev20240520-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-groupssettings:v1-rev20220614-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-healthcare:v1-rev20240130-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-iam:v2-rev20240530-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-iamcredentials:v1-rev20211203-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-monitoring:v3-rev20240829-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-monitoring:v3-rev20240929-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-pubsub:v1-rev20220904-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-sheets:v4-rev20240826-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-sqladmin:v1beta4-rev20240724-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-sheets:v4-rev20241001-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-sqladmin:v1beta4-rev20240925-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-storage:v1-rev20240319-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.apis:google-api-services-storage:v1-rev20240706-2.0.0=testRuntimeClasspath
com.google.apis:google-api-services-storage:v1-rev20240809-2.0.0=testCompileClasspath
com.google.auth:google-auth-library-credentials:1.24.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.24.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-storage:v1-rev20240924-2.0.0=testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-credentials:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.service:auto-service-annotations:1.0.1=errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.auto.service:auto-service-annotations:1.1.1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.service:auto-service:1.1.1=annotationProcessor
@@ -111,94 +107,89 @@ com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,errorprone,
com.google.auto.value:auto-value:1.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.value:auto-value:1.11.0=annotationProcessor,testAnnotationProcessor
com.google.auto:auto-common:1.2.1=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.closure-stylesheets:closure-stylesheets:1.5.0=css
com.google.cloud.bigdataoss:gcsio:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.bigdataoss:util:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.bigtable:bigtable-client-core-config:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.datastore:datastore-v1-proto-client:2.19.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.opentelemetry:detector-resources-support:0.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.cloud.opentelemetry:detector-resources-support:0.31.0=testRuntimeClasspath
com.google.cloud.opentelemetry:detector-resources-support:0.32.0=testRuntimeClasspath
com.google.cloud.opentelemetry:exporter-metrics:0.31.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud.opentelemetry:shared-resourcemapping:0.31.0=testRuntimeClasspath
com.google.cloud.sql:jdbc-socket-factory-core:1.20.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.sql:postgres-socket-factory:1.20.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
com.google.cloud.opentelemetry:shared-resourcemapping:0.32.0=testRuntimeClasspath
com.google.cloud.sql:jdbc-socket-factory-core:1.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.sql:postgres-socket-factory:1.21.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigquerystorage:3.5.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigtable:2.39.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-grpc:2.38.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-core-grpc:2.42.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-grpc:2.45.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-http:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-core-http:2.42.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-http:2.45.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core:2.38.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-core:2.42.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core:2.45.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-firestore:3.21.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-monitoring:3.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-nio:0.127.22=testCompileClasspath
com.google.cloud:google-cloud-nio:0.127.25=testCompileClasspath
com.google.cloud:google-cloud-nio:0.127.6=testRuntimeClasspath
com.google.cloud:google-cloud-pubsub:1.129.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-pubsublite:1.13.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-secretmanager:2.29.0=testRuntimeClasspath
com.google.cloud:google-cloud-secretmanager:2.48.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.cloud:google-cloud-secretmanager:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.cloud:google-cloud-spanner:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-storage:2.32.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-storage:2.42.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-storage:2.43.2=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-tasks:2.29.0=testRuntimeClasspath
com.google.cloud:google-cloud-tasks:2.48.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.cloud:google-cloud-tasks:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.cloud:grpc-gcp:1.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:libraries-bom:26.26.0=testRuntimeClasspath
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.21.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.code.findbugs:jsr305:3.0.1=css
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.code.gson:gson:2.10.1=soy
com.google.code.gson:gson:2.11.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.code.gson:gson:2.7=css,soy
com.google.common.html.types:types:1.0.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.common.html.types:types:1.0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.dagger:dagger-compiler:2.51.1=annotationProcessor,testAnnotationProcessor
com.google.dagger:dagger-spi:2.51.1=annotationProcessor,testAnnotationProcessor
com.google.dagger:dagger:2.51.1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.devtools.ksp:symbol-processing-api:1.9.20-1.0.14=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.20.0=soy
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.30.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle,soy
com.google.errorprone:error_prone_annotations:2.33.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_type_annotations:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:javac-shaded:9-dev-r4023-3=annotationProcessor,testAnnotationProcessor
com.google.errorprone:javac:9+181-r4173-1=errorproneJavac
com.google.escapevelocity:escapevelocity:0.9.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.escapevelocity:escapevelocity:1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.flatbuffers:flatbuffers-java:23.5.26=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger-system-backend:0.7.4=soy
com.google.flogger:flogger-system-backend:0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger:0.7.4=soy
com.google.flogger:flogger:0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:google-extensions:0.7.4=soy
com.google.flogger:google-extensions:0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.googlejavaformat:google-java-format:1.5=annotationProcessor,testAnnotationProcessor
com.google.guava:failureaccess:1.0.1=checkstyle,errorprone,nonprodAnnotationProcessor,soy
com.google.guava:failureaccess:1.0.2=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava-parent:32.1.1-jre=errorprone,nonprodAnnotationProcessor
com.google.guava:guava-testlib:33.3.0-jre=testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:20.0=css
com.google.guava:guava:31.0.1-jre=checkstyle,soy
com.google.guava:guava:32.1.1-jre=errorprone,nonprodAnnotationProcessor
com.google.guava:guava-parent:32.1.1-jre=errorprone,nonprodAnnotationProcessor,soy
com.google.guava:guava-testlib:33.3.1-jre=testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:31.0.1-jre=checkstyle
com.google.guava:guava:32.1.1-jre=errorprone,nonprodAnnotationProcessor,soy
com.google.guava:guava:33.0.0-jre=annotationProcessor,testAnnotationProcessor
com.google.guava:guava:33.2.1-jre=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.guava:guava:33.3.0-jre=testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:33.3.1-jre=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.gwt:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-apache-v2:1.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-appengine:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.http-client:google-http-client-appengine:1.44.2=testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-appengine:1.45.0=testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-gson:1.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-jackson2:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.http-client:google-http-client-jackson2:1.44.2=testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-jackson2:1.45.0=testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-protobuf:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client:1.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.inject.extensions:guice-multibindings:4.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.inject:guice:4.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.inject:guice:7.0.0=soy
com.google.j2objc:j2objc-annotations:1.3=checkstyle,soy
com.google.inject:guice:7.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.j2objc:j2objc-annotations:1.3=checkstyle
com.google.j2objc:j2objc-annotations:3.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.javascript:closure-compiler-externs:v20160713=css
com.google.javascript:closure-compiler-unshaded:v20160713=css
com.google.javascript:closure-compiler:v20210505=closureCompiler
com.google.jsinterop:jsinterop-annotations:1.0.1=soy
com.google.jsinterop:jsinterop-annotations:2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.monitoring-client:contrib:1.0.7=testCompileClasspath,testRuntimeClasspath
@@ -210,17 +201,14 @@ com.google.oauth-client:google-oauth-client-jetty:1.36.0=compileClasspath,deploy
com.google.oauth-client:google-oauth-client-servlet:1.34.1=testRuntimeClasspath
com.google.oauth-client:google-oauth-client-servlet:1.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.oauth-client:google-oauth-client:1.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java-util:3.25.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:2.5.0=css
com.google.protobuf:protobuf-java:3.13.0=soy
com.google.protobuf:protobuf-java-util:3.25.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.protobuf:protobuf-java:3.25.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:3.25.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.re2j:re2j:1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.template:soy:2021-02-01=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.template:soy:2024-02-26=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.truth:truth:1.4.4=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.googlecode.json-simple:json-simple:1.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.ibm.icu:icu4j:57.1=soy
com.ibm.icu:icu4j:73.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.ibm.icu:icu4j:73.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.jcraft:jsch:0.1.55=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.lmax:disruptor:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.puppycrawl.tools:checkstyle:9.3=checkstyle
@@ -245,18 +233,20 @@ com.squareup:kotlinpoet-jvm:1.15.1=compileClasspath,deploy_jar,nonprodCompileCla
com.squareup:kotlinpoet:1.11.0=annotationProcessor,testAnnotationProcessor
com.squareup:kotlinpoet:1.15.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.sun.istack:istack-commons-runtime:4.1.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.sun.xml.bind:jaxb-core:4.0.5=jaxb
com.sun.xml.bind:jaxb-impl:4.0.5=jaxb
com.sun.xml.bind:jaxb-osgi:4.0.5=jaxb
com.sun.xml.bind:jaxb-xjc:4.0.5=jaxb
com.zaxxer:HikariCP:5.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.sun.istack:istack-commons-runtime:4.1.2=jaxb
com.sun.istack:istack-commons-tools:4.1.2=jaxb
com.sun.xml.bind.external:relaxng-datatype:4.0.5=jaxb
com.sun.xml.bind.external:rngom:4.0.5=jaxb
com.sun.xml.dtd-parser:dtd-parser:1.5.1=jaxb
com.zaxxer:HikariCP:6.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-beanutils:commons-beanutils:1.9.4=checkstyle
commons-codec:commons-codec:1.17.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-collections:commons-collections:3.2.2=checkstyle
commons-dbutils:commons-dbutils:1.8.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-io:commons-io:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-io:commons-io:2.17.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-logging:commons-logging:1.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
dnsjava:dnsjava:3.6.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
dev.failsafe:failsafe:3.3.2=testCompileClasspath,testRuntimeClasspath
dnsjava:dnsjava:3.6.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0=testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0=testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_win32_x86:4.6.0=testRuntimeClasspath
@@ -269,29 +259,29 @@ io.apicurio:apicurio-registry-protobuf-schema-utilities:3.0.0.M2=compileClasspat
io.github.classgraph:classgraph:4.8.162=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-alts:1.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-api:1.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-auth:1.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-alts:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-api:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-auth:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-census:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-context:1.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-core:1.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-googleapis:1.66.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-grpclb:1.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-inprocess:1.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty-shaded:1.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-context:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-core:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-googleapis:1.67.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-grpclb:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-inprocess:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty-shaded:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-opentelemetry:1.66.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf-lite:1.66.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf:1.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-opentelemetry:1.67.1=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf-lite:1.67.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-rls:1.62.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-rls:1.66.0=testRuntimeClasspath
io.grpc:grpc-rls:1.67.1=testRuntimeClasspath
io.grpc:grpc-services:1.62.2=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-services:1.66.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-stub:1.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-services:1.67.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-stub:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-util:1.62.2=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-util:1.66.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-util:1.67.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-xds:1.62.2=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-xds:1.66.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-xds:1.67.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-buffer:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-http2:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-http:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -320,23 +310,25 @@ io.opencensus:opencensus-proto:0.2.0=compileClasspath,deploy_jar,nonprodCompileC
io.opentelemetry.contrib:opentelemetry-gcp-resources:1.37.0-alpha=testCompileClasspath,testRuntimeClasspath
io.opentelemetry.semconv:opentelemetry-semconv:1.25.0-alpha=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-api-incubator:1.37.0-alpha=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-api-incubator:1.41.0-alpha=testRuntimeClasspath
io.opentelemetry:opentelemetry-api-incubator:1.42.1-alpha=testRuntimeClasspath
io.opentelemetry:opentelemetry-api:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-api:1.41.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-api:1.42.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-bom:1.33.0=testRuntimeClasspath
io.opentelemetry:opentelemetry-context:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-context:1.41.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-context:1.42.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-exporter-logging:1.42.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.41.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.41.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.42.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.42.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.42.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.41.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.42.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.41.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.42.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.41.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.42.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk:1.41.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk:1.42.1=testCompileClasspath,testRuntimeClasspath
io.outfoxx:swiftpoet:1.3.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.perfmark:perfmark-api:0.27.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.smallrye:jandex:3.1.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -350,21 +342,19 @@ jakarta.servlet:jakarta.servlet-api:6.0.0=testCompileClasspath,testRuntimeClassp
jakarta.servlet:jakarta.servlet-api:6.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
jakarta.transaction:jakarta.transaction-api:2.0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=compileClasspath,deploy_jar,jaxb,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javacc:javacc:4.1=css
javax.annotation:javax.annotation-api:1.3.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javax.annotation:jsr250-api:1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
javax.inject:javax.inject:1=annotationProcessor,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
javax.inject:javax.inject:1=annotationProcessor,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
javax.jdo:jdo2-api:2.3-20090302111651=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javax.servlet:servlet-api:2.5=testRuntimeClasspath
javax.validation:validation-api:1.0.0.GA=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
joda-time:joda-time:2.12.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
junit:junit:4.13.2=nonprodCompileClasspath,nonprodRuntimeClasspath,testCompileClasspath,testRuntimeClasspath
net.arnx:nashorn-promise:0.1.1=testRuntimeClasspath
net.bytebuddy:byte-buddy-agent:1.15.0=testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy-agent:1.15.3=testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.14.12=compileClasspath,nonprodCompileClasspath
net.bytebuddy:byte-buddy:1.14.15=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
net.bytebuddy:byte-buddy:1.15.0=testCompileClasspath,testRuntimeClasspath
net.java.dev.javacc:javacc:4.1=css
net.bytebuddy:byte-buddy:1.15.3=testCompileClasspath,testRuntimeClasspath
net.java.dev.jna:jna:5.13.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
net.ltgt.gradle.incap:incap:0.2=annotationProcessor,testAnnotationProcessor
net.sf.saxon:Saxon-HE:10.6=checkstyle
@@ -377,7 +367,7 @@ org.antlr:antlr4:4.13.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonp
org.apache.arrow:arrow-format:15.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.arrow:arrow-memory-core:15.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.arrow:arrow-vector:15.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.avro:avro:1.11.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.avro:avro:1.12.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-fn-execution:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-job-management:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-pipeline:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -399,8 +389,8 @@ org.apache.beam:beam-sdks-java-transform-service-launcher:2.59.0=compileClasspat
org.apache.beam:beam-vendor-grpc-1_60_1:0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-vendor-guava-32_1_2-jre:0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-compress:1.26.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-csv:1.11.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-exec:1.3=testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-csv:1.12.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-exec:1.4.0=testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-lang3:3.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-text:1.12.0=testCompileClasspath,testRuntimeClasspath
org.apache.ftpserver:ftplet-api:1.2.0=testCompileClasspath,testRuntimeClasspath
@@ -408,56 +398,60 @@ org.apache.ftpserver:ftpserver-core:1.2.0=testCompileClasspath,testRuntimeClassp
org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.httpcomponents:httpcore:4.4.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.mina:mina-core:2.1.6=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-common:2.13.2=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-core:2.13.2=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-scp:2.13.2=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-sftp:2.13.2=testCompileClasspath,testRuntimeClasspath
org.apache.tomcat:tomcat-annotations-api:11.0.0-M25=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-common:2.14.0=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-core:2.14.0=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-scp:2.14.0=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-sftp:2.14.0=testCompileClasspath,testRuntimeClasspath
org.apache.tomcat:tomcat-annotations-api:11.0.0=testCompileClasspath,testRuntimeClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
org.bouncycastle:bcpg-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.bouncycastle:bcpkix-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.bouncycastle:bcprov-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.bouncycastle:bcutil-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.checkerframework:checker-compat-qual:2.5.3=compileClasspath,nonprodCompileClasspath,testCompileClasspath
org.checkerframework:checker-compat-qual:2.5.3=compileClasspath,nonprodCompileClasspath,soy,testCompileClasspath
org.checkerframework:checker-compat-qual:2.5.5=annotationProcessor,testAnnotationProcessor
org.checkerframework:checker-compat-qual:2.5.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.checkerframework:checker-qual:3.12.0=checkstyle,soy
org.checkerframework:checker-qual:3.33.0=errorprone,nonprodAnnotationProcessor
org.checkerframework:checker-qual:3.12.0=checkstyle
org.checkerframework:checker-qual:3.33.0=errorprone,nonprodAnnotationProcessor,soy
org.checkerframework:checker-qual:3.41.0=annotationProcessor,testAnnotationProcessor
org.checkerframework:checker-qual:3.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.checkerframework:checker-qual:3.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.codehaus.mojo:animal-sniffer-annotations:1.24=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.conscrypt:conscrypt-openjdk-uber:2.5.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.easymock:easymock:3.0=css
org.eclipse.angus:angus-activation:2.0.2=deploy_jar,jaxb,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.eclipse.angus:jakarta.mail:2.0.3=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.eclipse.collections:eclipse-collections-api:11.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.eclipse.collections:eclipse-collections:11.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.0.13=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.0.13=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-ee:12.0.13=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-http:12.0.13=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-io:12.0.13=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-security:12.0.13=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-server:12.0.13=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-session:12.0.13=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-util:12.0.13=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-xml:12.0.13=testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-core:10.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-database-postgresql:10.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.0.14=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.0.14=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-ee:12.0.14=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-http:12.0.14=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-io:12.0.14=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-security:12.0.14=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-server:12.0.14=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-session:12.0.14=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-util:12.0.14=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-xml:12.0.14=testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-core:10.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-database-postgresql:10.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.glassfish.jaxb:codemodel:4.0.5=jaxb
org.glassfish.jaxb:jaxb-core:4.0.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:jaxb-core:4.0.5=jaxb
org.glassfish.jaxb:jaxb-runtime:4.0.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:jaxb-runtime:4.0.5=jaxb
org.glassfish.jaxb:jaxb-xjc:4.0.5=jaxb
org.glassfish.jaxb:txw2:4.0.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:txw2:4.0.5=jaxb
org.glassfish.jaxb:xsom:4.0.5=jaxb
org.gwtproject:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest-core:1.1=css
org.hamcrest:hamcrest-core:1.3=nonprodCompileClasspath,nonprodRuntimeClasspath
org.hamcrest:hamcrest-core:3.0=testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest-library:3.0=testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest:2.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
org.hamcrest:hamcrest:3.0=testCompileClasspath,testRuntimeClasspath
org.hibernate.common:hibernate-commons-annotations:6.0.6.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-ant:6.5.2.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-core:6.5.2.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-hikaricp:6.5.2.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-ant:6.5.3.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-core:6.5.3.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-hikaricp:6.5.3.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
@@ -482,70 +476,72 @@ org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.0.1=deploy_jar,nonprodRun
org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains:annotations:13.0=annotationProcessor,testAnnotationProcessor
org.jetbrains:annotations:17.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jline:jline:3.26.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.joda:joda-money:1.0.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.json:json:20160212=soy
org.jline:jline:3.27.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.joda:joda-money:2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.json:json:20230618=soy
org.json:json:20240303=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jsoup:jsoup:1.18.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jspecify:jspecify:0.3.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.junit-pioneer:junit-pioneer:2.2.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-migrationsupport:5.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-launcher:1.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-runner:1.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-api:1.11.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-commons:1.11.0=testRuntimeClasspath
org.junit:junit-bom:5.11.0=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-core:1.10.19=css
org.mockito:mockito-core:5.13.0=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-junit-jupiter:5.13.0=testCompileClasspath,testRuntimeClasspath
org.objenesis:objenesis:2.1=css
org.jspecify:jspecify:0.3.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
org.jspecify:jspecify:1.0.0=testCompileClasspath,testRuntimeClasspath
org.junit-pioneer:junit-pioneer:2.3.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.11.2=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.11.2=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-migrationsupport:5.11.2=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.11.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.11.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.11.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-launcher:1.11.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-runner:1.11.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-api:1.11.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-commons:1.11.2=testRuntimeClasspath
org.junit:junit-bom:5.11.2=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-core:5.14.1=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-junit-jupiter:5.14.1=testCompileClasspath,testRuntimeClasspath
org.objenesis:objenesis:3.3=testRuntimeClasspath
org.ogce:xpp3:1.1.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-analysis:7.0=soy
org.ow2.asm:asm-analysis:9.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:7.0=soy
org.ow2.asm:asm-commons:9.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-analysis:9.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:9.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:9.7=jacocoAnt
org.ow2.asm:asm-tree:7.0=soy
org.ow2.asm:asm-tree:9.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-tree:9.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-tree:9.7=jacocoAnt
org.ow2.asm:asm-util:7.0=soy
org.ow2.asm:asm-util:9.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm:7.0=soy
org.ow2.asm:asm:9.2=compileClasspath,nonprodCompileClasspath
org.ow2.asm:asm-util:9.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm:9.5=compileClasspath,nonprodCompileClasspath,soy
org.ow2.asm:asm:9.7=deploy_jar,jacocoAnt,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
org.postgresql:postgresql:42.7.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.reflections:reflections:0.10.2=checkstyle
org.rnorth.duct-tape:duct-tape:1.0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-api:3.141.59=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chrome-driver:3.141.59=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-edge-driver:3.141.59=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-firefox-driver:3.141.59=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-ie-driver:3.141.59=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-java:3.141.59=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-opera-driver:3.141.59=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-remote-driver:3.141.59=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-safari-driver:3.141.59=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-support:3.141.59=testCompileClasspath,testRuntimeClasspath
org.slf4j:jcl-over-slf4j:1.7.32=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-api:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chrome-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chromium-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v127:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v128:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v129:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v85:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-edge-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-firefox-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-http:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-ie-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-java:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-json:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-manager:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-os:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-remote-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-safari-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-support:4.25.0=testCompileClasspath,testRuntimeClasspath
org.slf4j:jcl-over-slf4j:1.7.36=testCompileClasspath,testRuntimeClasspath
org.slf4j:jul-to-slf4j:1.7.30=testRuntimeClasspath
org.slf4j:slf4j-api:2.0.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.slf4j:slf4j-jdk14:2.0.13=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.snakeyaml:snakeyaml-engine:2.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.testcontainers:database-commons:1.20.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:jdbc:1.20.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:junit-jupiter:1.20.1=testCompileClasspath,testRuntimeClasspath
org.testcontainers:postgresql:1.20.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:selenium:1.20.1=testCompileClasspath,testRuntimeClasspath
org.testcontainers:testcontainers:1.20.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.threeten:threetenbp:1.6.9=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:database-commons:1.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:jdbc:1.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:junit-jupiter:1.20.2=testCompileClasspath,testRuntimeClasspath
org.testcontainers:postgresql:1.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:selenium:1.20.2=testCompileClasspath,testRuntimeClasspath
org.testcontainers:testcontainers:1.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.threeten:threetenbp:1.7.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.w3c.css:sac:1.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.webjars.npm:viz.js-graphviz-java:2.1.3=testRuntimeClasspath
org.xerial.snappy:snappy-java:1.1.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath

View File

@@ -24,7 +24,7 @@ import com.google.common.collect.Multimap;
import com.google.common.flogger.FluentLogger;
import google.registry.model.EppResource;
import google.registry.persistence.VKey;
import google.registry.request.Action.Service;
import google.registry.request.Action;
import javax.inject.Inject;
import org.joda.time.DateTime;
import org.joda.time.Duration;
@@ -78,7 +78,7 @@ public final class AsyncTaskEnqueuer {
logger.atInfo().log("Enqueuing async re-save of %s to run at %s.", entityKey, whenToResave);
cloudTasksUtils.enqueue(
QUEUE_ASYNC_ACTIONS,
cloudTasksUtils.createPostTaskWithDelay(
ResaveEntityAction.PATH, Service.BACKEND, params, etaDuration));
cloudTasksUtils.createTaskWithDelay(
ResaveEntityAction.class, Action.Method.POST, params, etaDuration));
}
}

View File

@@ -20,6 +20,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.flogger.FluentLogger;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.UrlConnectionService;
@@ -42,7 +43,7 @@ import javax.net.ssl.HttpsURLConnection;
* --service BACKEND -X POST -u '/_dr/task/executeCannedScript}'}
*/
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = "/_dr/task/executeCannedScript",
method = {POST, GET},
automaticallyPrintOk = true,

View File

@@ -13,6 +13,7 @@
// limitations under the License.
package google.registry.batch;
import static google.registry.persistence.PersistenceModule.TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
@@ -26,7 +27,7 @@ import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.BulkPricingPackage;
import google.registry.model.registrar.Registrar;
import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.Action.GaeService;
import google.registry.request.auth.Auth;
import google.registry.ui.server.SendEmailUtils;
import google.registry.util.Clock;
@@ -38,7 +39,7 @@ import org.joda.time.Days;
* An action that checks all {@link BulkPricingPackage} objects for compliance with their max create
* limit.
*/
@Action(service = Service.BACKEND, path = CheckBulkComplianceAction.PATH, auth = Auth.AUTH_ADMIN)
@Action(service = GaeService.BACKEND, path = CheckBulkComplianceAction.PATH, auth = Auth.AUTH_ADMIN)
public class CheckBulkComplianceAction implements Runnable {
public static final String PATH = "/_dr/task/checkBulkCompliance";
@@ -89,7 +90,7 @@ public class CheckBulkComplianceAction implements Runnable {
@Override
public void run() {
tm().transact(this::checkBulkPackages);
tm().transact(TRANSACTION_REPEATABLE_READ, this::checkBulkPackages);
}
private void checkBulkPackages() {

View File

@@ -15,8 +15,8 @@
package google.registry.batch;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.tools.ServiceConnection.getServer;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.api.gax.rpc.ApiException;
@@ -28,6 +28,7 @@ import com.google.cloud.tasks.v2.QueueName;
import com.google.cloud.tasks.v2.Task;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.Streams;
import com.google.common.escape.Escaper;
@@ -39,11 +40,15 @@ import com.google.protobuf.ByteString;
import com.google.protobuf.util.Timestamps;
import google.registry.config.CredentialModule.ApplicationDefaultCredential;
import google.registry.config.RegistryConfig.Config;
import google.registry.request.Action;
import google.registry.request.Action.Method;
import google.registry.request.Action.Service;
import google.registry.util.Clock;
import google.registry.util.CollectionUtils;
import google.registry.util.GoogleCredentialsBundle;
import google.registry.util.RegistryEnvironment;
import google.registry.util.Retrier;
import java.io.Serial;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@@ -58,7 +63,7 @@ import org.joda.time.Duration;
/** Utilities for dealing with Cloud Tasks. */
public class CloudTasksUtils implements Serializable {
private static final long serialVersionUID = -7605156291755534069L;
@Serial private static final long serialVersionUID = -7605156291755534069L;
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final Random random = new Random();
@@ -122,7 +127,7 @@ public class CloudTasksUtils implements Serializable {
*/
private static String processRequestParameters(
String path,
HttpMethod method,
Method method,
Multimap<String, String> params,
BiConsumer<String, String> putHeadersFunction,
Consumer<ByteString> setBodyFunction) {
@@ -140,7 +145,7 @@ public class CloudTasksUtils implements Serializable {
"%s=%s",
escaper.escape(entry.getKey()), escaper.escape(entry.getValue())))
.collect(toImmutableList()));
if (method.equals(HttpMethod.GET)) {
if (method.equals(Method.GET)) {
return String.format("%s?%s", path, encodedParams);
}
putHeadersFunction.accept(HttpHeaders.CONTENT_TYPE, MediaType.FORM_DATA.toString());
@@ -155,9 +160,12 @@ public class CloudTasksUtils implements Serializable {
* default service account as the principal. That account must have permission to submit tasks to
* Cloud Tasks.
*
* <p>The caller of this method is responsible for passing in the appropriate service based on the
* runtime (GAE/GKE). Use the overload that takes an action class if possible.
*
* @param path the relative URI (staring with a slash and ending without one).
* @param method the HTTP method to be used for the request, only GET and POST are supported.
* @param service the App Engine service to route the request to.
* @param method the HTTP method to be used for the request.
* @param service the GAE/GKE service to route the request to.
* @param params a multimap of URL query parameters. Duplicate keys are saved as is, and it is up
* to the server to process the duplicate keys.
* @return the enqueued task.
@@ -165,16 +173,13 @@ public class CloudTasksUtils implements Serializable {
* href=ttps://cloud.google.com/appengine/docs/standard/java/taskqueue/push/creating-tasks#target>Specifyinig
* the worker service</a>
*/
private Task createTask(
String path, HttpMethod method, Service service, Multimap<String, String> params) {
protected Task createTask(
String path, Method method, Service service, Multimap<String, String> params) {
checkArgument(
path != null && !path.isEmpty() && path.charAt(0) == '/',
"The path must start with a '/'.");
checkArgument(
method.equals(HttpMethod.GET) || method.equals(HttpMethod.POST),
"HTTP method %s is used. Only GET and POST are allowed.",
method);
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder().setHttpMethod(method);
HttpRequest.Builder requestBuilder =
HttpRequest.newBuilder().setHttpMethod(HttpMethod.valueOf(method.name()));
path =
processRequestParameters(
path, method, params, requestBuilder::putHeaders, requestBuilder::setBody);
@@ -183,17 +188,59 @@ public class CloudTasksUtils implements Serializable {
.setServiceAccountEmail(credential.serviceAccount())
.setAudience(oauthClientId);
requestBuilder.setOidcToken(oidcTokenBuilder.build());
String totalPath = String.format("%s%s", getServer(service), path);
String totalPath = String.format("%s%s", service.getServiceUrl(), path);
requestBuilder.setUrl(totalPath);
return Task.newBuilder().setHttpRequest(requestBuilder.build()).build();
}
/**
* Create a {@link Task} to be enqueued.
*
* <p>This uses the standard Cloud Tasks auth format to create and send an OIDC ID token with the
* default service account as the principal. That account must have permission to submit tasks to
* Cloud Tasks.
*
* <p>Prefer this overload over the one where the path and service are explicit defined, as this
* class will automatically determine the service to use based on the action and the runtime.
*
* @param actionClazz the action class to run, must be annotated with {@link Action}.
* @param method the HTTP method to be used for the request.
* @param params a multimap of URL query parameters. Duplicate keys are saved as is, and it is up
* to the server to process the duplicate keys.
* @return the enqueued task.
* @see <a
* href=ttps://cloud.google.com/appengine/docs/standard/java/taskqueue/push/creating-tasks#target>Specifyinig
* the worker service</a>
*/
public Task createTask(
Class<? extends Runnable> actionClazz, Method method, Multimap<String, String> params) {
Action action = actionClazz.getAnnotation(Action.class);
checkArgument(
action != null,
"Action class %s is not annotated with @Action",
actionClazz.getSimpleName());
String path = action.path();
ImmutableSet<Method> allowedMethods = ImmutableSet.copyOf(action.method());
checkArgument(
allowedMethods.contains(method),
"Method %s is not allowed for action %s. Allowed methods are %s",
method,
actionClazz.getSimpleName(),
allowedMethods);
Service service =
RegistryEnvironment.isOnJetty() ? Action.ServiceGetter.get(action) : action.service();
return createTask(path, method, service, params);
}
/**
* Create a {@link Task} to be enqueued with a random delay up to {@code jitterSeconds}.
*
* <p>The caller of this method is responsible for passing in the appropriate service based on the
* runtime (GAE/GKE). Use the overload that takes an action class if possible.
*
* @param path the relative URI (staring with a slash and ending without one).
* @param method the HTTP method to be used for the request, only GET and POST are supported.
* @param service the App Engine service to route the request to.
* @param method the HTTP method to be used for the request.
* @param service the GAE/GKE service to route the request to.
* @param params a multimap of URL query parameters. Duplicate keys are saved as is, and it is up
* to the server to process the duplicate keys.
* @param jitterSeconds the number of seconds that a task is randomly delayed up to.
@@ -202,9 +249,9 @@ public class CloudTasksUtils implements Serializable {
* href=ttps://cloud.google.com/appengine/docs/standard/java/taskqueue/push/creating-tasks#target>Specifyinig
* the worker service</a>
*/
private Task createTaskWithJitter(
public Task createTaskWithJitter(
String path,
HttpMethod method,
Method method,
Service service,
Multimap<String, String> params,
Optional<Integer> jitterSeconds) {
@@ -219,12 +266,44 @@ public class CloudTasksUtils implements Serializable {
Duration.millis(random.nextInt((int) SECONDS.toMillis(jitterSeconds.get()))));
}
/**
* Create a {@link Task} to be enqueued with a random delay up to {@code jitterSeconds}.
*
* <p>Prefer this overload over the one where the path and service are explicit defined, as this
* class will automatically determine the service to use based on the action and the runtime.
*
* @param actionClazz the action class to run, must be annotated with {@link Action}.
* @param method the HTTP method to be used for the request.
* @param params a multimap of URL query parameters. Duplicate keys are saved as is, and it is up
* to the server to process the duplicate keys.
* @param jitterSeconds the number of seconds that a task is randomly delayed up to.
* @return the enqueued task.
* @see <a
* href=ttps://cloud.google.com/appengine/docs/standard/java/taskqueue/push/creating-tasks#target>Specifyinig
* the worker service</a>
*/
public Task createTaskWithJitter(
Class<? extends Runnable> actionClazz,
Method method,
Multimap<String, String> params,
Optional<Integer> jitterSeconds) {
Action action = getAction(actionClazz);
checkState(
action != null,
"Action class %s is not annotated with @Action",
actionClazz.getSimpleName());
String path = action.path();
Service service =
RegistryEnvironment.isOnJetty() ? Action.ServiceGetter.get(action) : action.service();
return createTaskWithJitter(path, method, service, params, jitterSeconds);
}
/**
* Create a {@link Task} to be enqueued with delay of {@code duration}.
*
* @param path the relative URI (staring with a slash and ending without one).
* @param method the HTTP method to be used for the request, only GET and POST are supported.
* @param service the App Engine service to route the request to.
* @param method the HTTP method to be used for the request.
* @param service the GAE/GKE service to route the request to.
* @param params a multimap of URL query parameters. Duplicate keys are saved as is, and it is up
* to the server to process the duplicate keys.
* @param delay the amount of time that a task needs to delayed for.
@@ -235,7 +314,7 @@ public class CloudTasksUtils implements Serializable {
*/
private Task createTaskWithDelay(
String path,
HttpMethod method,
Method method,
Service service,
Multimap<String, String> params,
Duration delay) {
@@ -248,58 +327,53 @@ public class CloudTasksUtils implements Serializable {
.build();
}
public Task createPostTask(String path, Service service, Multimap<String, String> params) {
return createTask(path, HttpMethod.POST, service, params);
}
public Task createGetTask(String path, Service service, Multimap<String, String> params) {
return createTask(path, HttpMethod.GET, service, params);
}
/**
* Create a {@link Task} via HTTP.POST that will be randomly delayed up to {@code jitterSeconds}.
* Create a {@link Task} to be enqueued with delay of {@code duration}.
*
* <p>Prefer this overload over the one where the path and service are explicit defined, as this
* class will automatically determine the service to use based on the action and the runtime.
*
* @param actionClazz the action class to run, must be annotated with {@link Action}.
* @param method the HTTP method to be used for the request.
* @param params a multimap of URL query parameters. Duplicate keys are saved as is, and it is up
* to the server to process the duplicate keys.
* @param delay the amount of time that a task needs to delayed for.
* @return the enqueued task.
* @see <a
* href=ttps://cloud.google.com/appengine/docs/standard/java/taskqueue/push/creating-tasks#target>Specifyinig
* the worker service</a>
*/
public Task createPostTaskWithJitter(
String path,
Service service,
public Task createTaskWithDelay(
Class<? extends Runnable> actionClazz,
Method method,
Multimap<String, String> params,
Optional<Integer> jitterSeconds) {
return createTaskWithJitter(path, HttpMethod.POST, service, params, jitterSeconds);
Duration delay) {
Action action = getAction(actionClazz);
String path = action.path();
Service service =
RegistryEnvironment.isOnJetty() ? Action.ServiceGetter.get(action) : action.service();
return createTaskWithDelay(path, method, service, params, delay);
}
/**
* Create a {@link Task} via HTTP.GET that will be randomly delayed up to {@code jitterSeconds}.
*/
public Task createGetTaskWithJitter(
String path,
Service service,
Multimap<String, String> params,
Optional<Integer> jitterSeconds) {
return createTaskWithJitter(path, HttpMethod.GET, service, params, jitterSeconds);
}
/** Create a {@link Task} via HTTP.POST that will be delayed for {@code delay}. */
public Task createPostTaskWithDelay(
String path, Service service, Multimap<String, String> params, Duration delay) {
return createTaskWithDelay(path, HttpMethod.POST, service, params, delay);
}
/** Create a {@link Task} via HTTP.GET that will be delayed for {@code delay}. */
public Task createGetTaskWithDelay(
String path, Service service, Multimap<String, String> params, Duration delay) {
return createTaskWithDelay(path, HttpMethod.GET, service, params, delay);
private static Action getAction(Class<? extends Runnable> actionClazz) {
Action action = actionClazz.getAnnotation(Action.class);
checkState(
action != null,
"Action class %s is not annotated with @Action",
actionClazz.getSimpleName());
return action;
}
public abstract static class SerializableCloudTasksClient implements Serializable {
private static final long serialVersionUID = 7872861868968535498L;
@Serial private static final long serialVersionUID = 7872861868968535498L;
public abstract Task enqueue(String projectId, String locationId, String queueName, Task task);
}
public static class GcpCloudTasksClient extends SerializableCloudTasksClient {
private static final long serialVersionUID = -5959253033129154037L;
@Serial private static final long serialVersionUID = -5959253033129154037L;
// Use a supplier so that we can use try-with-resources with the client, which implements
// Autocloseable.

View File

@@ -37,6 +37,7 @@ import google.registry.model.eppcommon.ProtocolDefinition;
import google.registry.model.eppoutput.EppOutput;
import google.registry.persistence.transaction.QueryComposer.Comparator;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.request.lock.LockHandler;
@@ -67,7 +68,7 @@ import org.joda.time.Duration;
* this action runs, thus alerting us that human action is needed to correctly process the delete.
*/
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = DeleteExpiredDomainsAction.PATH,
auth = Auth.AUTH_ADMIN)
public class DeleteExpiredDomainsAction implements Runnable {

View File

@@ -16,6 +16,7 @@ package google.registry.batch;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.persistence.PersistenceModule.TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.request.RequestParameters.PARAM_DRY_RUN;
@@ -36,6 +37,7 @@ import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.HistoryEntryDao;
import google.registry.persistence.VKey;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
@@ -53,7 +55,7 @@ import javax.inject.Inject;
* production.
*/
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = "/_dr/task/deleteLoadTestData",
method = POST,
auth = Auth.AUTH_ADMIN)
@@ -90,6 +92,7 @@ public class DeleteLoadTestDataAction implements Runnable {
"This action is not safe to run on PRODUCTION.");
tm().transact(
TRANSACTION_REPEATABLE_READ,
() -> {
LOAD_TEST_REGISTRARS.forEach(this::deletePollMessages);
tm().loadAllOfStream(Contact.class).forEach(this::deleteContact);

View File

@@ -42,6 +42,7 @@ import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.tld.Tld.TldType;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.util.RegistryEnvironment;
@@ -58,7 +59,7 @@ import org.joda.time.Duration;
* billing events, along with their ForeignKeyDomainIndex entities.
*/
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = "/_dr/task/deleteProberData",
method = POST,
auth = Auth.AUTH_ADMIN)

View File

@@ -35,6 +35,7 @@ import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingRecurrence;
import google.registry.model.common.Cursor;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
@@ -50,7 +51,7 @@ import org.joda.time.DateTime;
* BillingRecurrence} billing events into synthetic {@link BillingEvent} events.
*/
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = "/_dr/task/expandBillingRecurrences",
auth = Auth.AUTH_ADMIN)
public class ExpandBillingRecurrencesAction implements Runnable {

View File

@@ -35,6 +35,7 @@ import google.registry.model.registrar.RegistrarPoc;
import google.registry.model.tld.RegistryLockDao;
import google.registry.persistence.VKey;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
@@ -49,7 +50,7 @@ import org.joda.time.Duration;
/** Task that re-locks a previously-Registry-Locked domain after a predetermined period of time. */
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = RelockDomainAction.PATH,
method = POST,
automaticallyPrintOk = true,

View File

@@ -28,6 +28,7 @@ import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.config.RegistryConfig.Config;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
@@ -53,7 +54,7 @@ import javax.inject.Inject;
* <p>This runs the {@link google.registry.beam.resave.ResaveAllEppResourcesPipeline}.
*/
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = ResaveAllEppResourcesPipelineAction.PATH,
auth = Auth.AUTH_ADMIN)
public class ResaveAllEppResourcesPipelineAction implements Runnable {

View File

@@ -25,6 +25,7 @@ import com.google.common.flogger.FluentLogger;
import google.registry.model.EppResource;
import google.registry.persistence.VKey;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Action.Method;
import google.registry.request.Parameter;
import google.registry.request.Response;
@@ -39,7 +40,7 @@ import org.joda.time.DateTime;
* <p>{@link EppResource}s will be projected forward to the current time.
*/
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = ResaveEntityAction.PATH,
auth = Auth.AUTH_ADMIN,
method = Method.POST)

View File

@@ -35,6 +35,7 @@ import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.RegistrarPoc;
import google.registry.model.registrar.RegistrarPocBase.Type;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.EmailMessage;
@@ -49,7 +50,7 @@ import org.joda.time.format.DateTimeFormatter;
/** An action that sends notification emails to registrars whose certificates are expiring soon. */
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = SendExpiringCertificateNotificationEmailAction.PATH,
auth = Auth.AUTH_ADMIN)
public class SendExpiringCertificateNotificationEmailAction implements Runnable {

View File

@@ -30,7 +30,7 @@ import google.registry.beam.wipeout.WipeOutContactHistoryPiiPipeline;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.contact.ContactHistory;
import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
@@ -49,7 +49,7 @@ import org.joda.time.DateTime;
* time.
*/
@Action(
service = Service.BACKEND,
service = GaeService.BACKEND,
path = WipeOutContactHistoryPiiAction.PATH,
auth = Auth.AUTH_ADMIN)
public class WipeOutContactHistoryPiiAction implements Runnable {

View File

@@ -36,6 +36,7 @@ import google.registry.config.RegistryConfig.ConfigModule;
import google.registry.flows.custom.CustomLogicFactoryModule;
import google.registry.flows.custom.CustomLogicModule;
import google.registry.flows.domain.DomainPricingLogic;
import google.registry.flows.domain.DomainPricingLogic.AllocationTokenInvalidForCurrencyException;
import google.registry.flows.domain.DomainPricingLogic.AllocationTokenInvalidForPremiumNameException;
import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingBase.Flag;
@@ -414,7 +415,8 @@ public class ExpandBillingRecurrencesPipeline implements Serializable {
.setCancellationMatchingBillingEvent(billingRecurrence)
.setTargetId(billingRecurrence.getTargetId())
.build();
} catch (AllocationTokenInvalidForPremiumNameException e) {
} catch (AllocationTokenInvalidForCurrencyException
| AllocationTokenInvalidForPremiumNameException e) {
// This should not be reached since we are not using an allocation token
return;
}

View File

@@ -44,7 +44,7 @@ import google.registry.rde.RdeModule;
import google.registry.rde.RdeResourceType;
import google.registry.rde.RdeUploadAction;
import google.registry.rde.RdeUtils;
import google.registry.request.Action.Service;
import google.registry.request.Action;
import google.registry.request.RequestParameters;
import google.registry.tldconfig.idn.IdnTableEnum;
import google.registry.xjc.rdeheader.XjcRdeHeader;
@@ -302,9 +302,9 @@ public class RdeIO {
if (key.mode() == RdeMode.FULL) {
cloudTasksUtils.enqueue(
RDE_UPLOAD_QUEUE,
cloudTasksUtils.createPostTaskWithDelay(
RdeUploadAction.PATH,
Service.BACKEND,
cloudTasksUtils.createTaskWithDelay(
RdeUploadAction.class,
Action.Method.POST,
ImmutableMultimap.of(
RequestParameters.PARAM_TLD,
key.tld(),
@@ -314,9 +314,9 @@ public class RdeIO {
} else {
cloudTasksUtils.enqueue(
BRDA_QUEUE,
cloudTasksUtils.createPostTaskWithDelay(
BrdaCopyAction.PATH,
Service.BACKEND,
cloudTasksUtils.createTaskWithDelay(
BrdaCopyAction.class,
Action.Method.POST,
ImmutableMultimap.of(
RequestParameters.PARAM_TLD,
key.tld(),

View File

@@ -41,6 +41,7 @@ import google.registry.bsa.persistence.DownloadScheduler;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.tld.Tlds;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
@@ -50,7 +51,7 @@ import java.util.stream.Stream;
import javax.inject.Inject;
@Action(
service = Action.Service.BSA,
service = GaeService.BSA,
path = BsaDownloadAction.PATH,
method = {GET, POST},
auth = Auth.AUTH_ADMIN)

View File

@@ -31,6 +31,7 @@ import google.registry.bsa.persistence.RefreshScheduler;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.tld.Tlds;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.BatchedStreams;
@@ -41,7 +42,7 @@ import javax.inject.Inject;
import org.joda.time.Duration;
@Action(
service = Action.Service.BSA,
service = GaeService.BSA,
path = BsaRefreshAction.PATH,
method = {GET, POST},
auth = Auth.AUTH_ADMIN)

View File

@@ -55,6 +55,7 @@ import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldType;
import google.registry.persistence.VKey;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
@@ -67,7 +68,7 @@ import org.joda.time.Duration;
/** Validates the BSA data in the database against the most recent block lists. */
@Action(
service = Action.Service.BSA,
service = GaeService.BSA,
path = BsaValidateAction.PATH,
method = {GET, POST},
auth = Auth.AUTH_ADMIN)

View File

@@ -42,7 +42,7 @@ import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldType;
import google.registry.model.tld.label.ReservedList;
import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.Action.GaeService;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import jakarta.persistence.TypedQuery;
@@ -72,7 +72,7 @@ import org.joda.time.DateTime;
* <p>The file is also uploaded to GCS to preserve it as a record for ourselves.
*/
@Action(
service = Service.BSA,
service = GaeService.BSA,
path = "/_dr/task/uploadBsaUnavailableNames",
method = {GET, POST},
auth = Auth.AUTH_ADMIN)

View File

@@ -15,6 +15,8 @@
package google.registry.config;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
/** Helper methods for configuration classes. */
@@ -23,12 +25,12 @@ public final class ConfigUtils {
/**
* Creates a URL instance.
*
* @throws RuntimeException to rethrow {@link MalformedURLException}
* @throws RuntimeException to rethrow {@link URISyntaxException} or {@link MalformedURLException}
*/
public static URL makeUrl(String url) {
try {
return new URL(url);
} catch (MalformedURLException e) {
return new URI(url).toURL();
} catch (URISyntaxException | MalformedURLException e) {
throw new RuntimeException(e);
}
}

View File

@@ -37,6 +37,7 @@ import google.registry.bsa.UploadBsaUnavailableDomainsAction;
import google.registry.dns.ReadDnsRefreshRequestsAction;
import google.registry.model.common.DnsRefreshRequest;
import google.registry.persistence.transaction.JpaTransactionManager;
import google.registry.request.Action.GkeService;
import google.registry.util.RegistryEnvironment;
import google.registry.util.YamlUtils;
import jakarta.mail.internet.AddressException;
@@ -45,8 +46,6 @@ import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.net.URI;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
@@ -137,22 +136,10 @@ public final class RegistryConfig {
return config.gcpProject.locationId;
}
/**
* The filename of the logo to be displayed in the header of the registrar console.
*
* @see google.registry.ui.server.registrar.ConsoleUiAction
*/
@Provides
@Config("logoFilename")
public static String provideLogoFilename(RegistryConfigSettings config) {
return config.registrarConsole.logoFilename;
}
/**
* The product name of this specific registry. Used throughout the registrar console.
*
* @see google.registry.ui.server.registrar.ConsoleUiAction
* @see google.registry.ui.server.console.ConsoleUserDataAction
*/
@Provides
@Config("productName")
@@ -179,23 +166,11 @@ public final class RegistryConfig {
return config.misc.isEmailSendingEnabled;
}
/**
* The e-mail address for questions about integrating with the registry. Used in the
* "contact-us" section of the registrar console.
*
* @see google.registry.ui.server.registrar.ConsoleUiAction
*/
@Provides
@Config("integrationEmail")
public static String provideIntegrationEmail(RegistryConfigSettings config) {
return config.registrarConsole.integrationEmailAddress;
}
/**
* The e-mail address for general support. Used in the "contact-us" section of the registrar
* console.
*
* @see google.registry.ui.server.registrar.ConsoleUiAction
* @see google.registry.ui.server.console.ConsoleUserDataAction
*/
@Provides
@Config("supportEmail")
@@ -203,18 +178,6 @@ public final class RegistryConfig {
return config.registrarConsole.supportEmailAddress;
}
/**
* The "From" e-mail address for announcements. Used in the "contact-us" section of the
* registrar console.
*
* @see google.registry.ui.server.registrar.ConsoleUiAction
*/
@Provides
@Config("announcementsEmail")
public static String provideAnnouncementsEmail(RegistryConfigSettings config) {
return config.registrarConsole.announcementsEmailAddress;
}
/**
* The DUM file name, used as a file name base for DUM csv file
*
@@ -229,7 +192,7 @@ public final class RegistryConfig {
/**
* The contact phone number. Used in the "contact-us" section of the registrar console.
*
* @see google.registry.ui.server.registrar.ConsoleUiAction
* @see google.registry.ui.server.console.ConsoleUserDataAction
*/
@Provides
@Config("supportPhoneNumber")
@@ -241,7 +204,7 @@ public final class RegistryConfig {
* The URL for technical support docs. Used in the "contact-us" section of the registrar
* console.
*
* @see google.registry.ui.server.registrar.ConsoleUiAction
* @see google.registry.ui.server.console.ConsoleUserDataAction
*/
@Provides
@Config("technicalDocsUrl")
@@ -249,22 +212,6 @@ public final class RegistryConfig {
return config.registrarConsole.technicalDocsUrl;
}
/**
* Configuration for analytics services installed in the web console.
*
* @see google.registry.ui.server.registrar.ConsoleUiAction
* @see google.registry.ui.soy.registrar.AnalyticsSoyInfo
*/
@Provides
@Config("analyticsConfig")
public static Map<String, Object> provideAnalyticsConfig(RegistryConfigSettings config) {
// Can't be an ImmutableMap because it may contain null values.
HashMap<String, Object> analyticsConfig = new HashMap<>();
analyticsConfig.put(
"googleAnalyticsId", config.registrarConsole.analyticsConfig.googleAnalyticsId);
return Collections.unmodifiableMap(analyticsConfig);
}
/**
* Returns the Google Cloud Storage bucket for storing zone files.
*
@@ -519,7 +466,7 @@ public final class RegistryConfig {
* Returns the email address(es) that notifications of registrar and/or registrar contact
* updates should be sent to, or the empty list if updates should not be sent.
*
* @see google.registry.ui.server.registrar.RegistrarSettingsAction
* @see google.registry.ui.server.SendEmailUtils
*/
@Provides
@Config("registrarChangesNotificationEmailAddresses")
@@ -913,17 +860,6 @@ public final class RegistryConfig {
return URI.create(config.rde.uploadUrl);
}
/**
* Whether or not the registrar console is enabled.
*
* @see google.registry.ui.server.registrar.ConsoleUiAction
*/
@Provides
@Config("registrarConsoleEnabled")
public static boolean provideRegistrarConsoleEnabled() {
return true;
}
/**
* Maximum amount of time for syncing a spreadsheet, before killing.
*
@@ -1593,6 +1529,14 @@ public final class RegistryConfig {
return CONFIG_SETTINGS.get().gcpProject.isLocal;
}
public static String getBaseDomain() {
return CONFIG_SETTINGS.get().gcpProject.baseDomain;
}
public static URL getServiceUrl(GkeService service) {
return makeUrl(String.format("https://%s.%s", service.getServiceId(), getBaseDomain()));
}
/**
* Returns the address of the Nomulus app default HTTP server.
*
@@ -1799,6 +1743,17 @@ public final class RegistryConfig {
CONFIG_SETTINGS.get().registryPolicy.tieredPricingPromotionRegistrarIds);
}
/**
* Set of registrars for which we do not send poll messages on standard domain deletion.
*
* <p>For these registrars we won't send a poll message in order to avoid database contention. See
* b/379331882 for more details.
*/
public static ImmutableSet<String> getNoPollMessageOnDeletionRegistrarIds() {
return ImmutableSet.copyOf(
CONFIG_SETTINGS.get().registryPolicy.noPollMessageOnDeletionRegistrarIds);
}
/**
* Memoizes loading of the {@link RegistryConfigSettings} POJO.
*

View File

@@ -115,6 +115,7 @@ public class RegistryConfigSettings {
public boolean requireSslCertificates;
public double sunriseDomainCreateDiscount;
public Set<String> tieredPricingPromotionRegistrarIds;
public Set<String> noPollMessageOnDeletionRegistrarIds;
}
/** Configuration for Hibernate. */
@@ -189,18 +190,9 @@ public class RegistryConfigSettings {
/** Configuration for the web-based registrar console. */
public static class RegistrarConsole {
public String dumFileName;
public String logoFilename;
public String supportPhoneNumber;
public String supportEmailAddress;
public String announcementsEmailAddress;
public String integrationEmailAddress;
public String technicalDocsUrl;
public AnalyticsConfig analyticsConfig;
}
/** Configuration for analytics services installed in the registrar console */
public static class AnalyticsConfig {
public String googleAnalyticsId;
}
/** Configuration for monitoring. */

View File

@@ -220,6 +220,9 @@ registryPolicy:
# In addition, we will return the non-promotional (i.e. incorrect) price on
# domain create requests.
tieredPricingPromotionRegistrarIds: []
# List of registrars for which we won't send poll message on standard domain
# deletions.
noPollMessageOnDeletionRegistrarIds: []
hibernate:
# If set to false, calls to tm().transact() cannot be nested. If set to true,
@@ -372,6 +375,11 @@ credentialOAuth:
delegatedCredentialOauthScopes:
# View and manage groups on your domain in Directory API.
- https://www.googleapis.com/auth/admin.directory.group
# View and manage users in Google Workspace
- https://www.googleapis.com/auth/admin.directory.user
# Security scope which seems to be required to create users via API,
# based on https://github.com/googleapis/google-api-nodejs-client/issues/1884
- https://www.googleapis.com/auth/admin.directory.user.security
# View and manage group settings in Group Settings API.
- https://www.googleapis.com/auth/apps.groups.settings
# Send email through Gmail.
@@ -420,30 +428,15 @@ registrarConsole:
# DUM download file name, excluding the extension
dumFileName: dum_file_name
# Filename of the logo to use in the header of the console. This filename is
# relative to ui/assets/images/
logoFilename: logo.png
# Contact phone number for support with the registry.
supportPhoneNumber: +1 (888) 555 0123
# Contact email address for support with the registry.
supportEmailAddress: support@example.com
# From: email address used to send announcements from the registry.
announcementsEmailAddress: announcements@example.com
# Contact email address for questions about integrating with the registry.
integrationEmailAddress: integration@example.com
# URL linking to directory of technical support docs on the registry.
technicalDocsUrl: http://example.com/your_support_docs/
# Configuration for all analytics services installed in the web console
analyticsConfig:
# Google Analytics account where data on console use is sent, optional
googleAnalyticsId: null
monitoring:
# Max queries per second for the Google Cloud Monitoring V3 (aka Stackdriver)
# API. The limit can be adjusted by contacting Cloud Support.

View File

@@ -11,6 +11,8 @@ registryPolicy:
Line 2 is this 1.
tieredPricingPromotionRegistrarIds:
- NewRegistrar
noPollMessageOnDeletionRegistrarIds:
- NewRegistrar
caching:
singletonCacheRefreshSeconds: 0

View File

@@ -40,12 +40,14 @@ import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import google.registry.batch.CloudTasksUtils;
import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.Action.GaeService;
import google.registry.request.Action.GkeService;
import google.registry.request.Parameter;
import google.registry.request.ParameterMap;
import google.registry.request.RequestParameters;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.RegistryEnvironment;
import java.util.Optional;
import java.util.stream.Stream;
import javax.inject.Inject;
@@ -78,7 +80,7 @@ import javax.inject.Inject;
* </ul>
*/
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = "/_dr/cron/fanout",
automaticallyPrintOk = true,
auth = Auth.AUTH_ADMIN)
@@ -157,7 +159,11 @@ public final class TldFanoutAction implements Runnable {
params = ArrayListMultimap.create(params);
params.put(RequestParameters.PARAM_TLD, tld);
}
return cloudTasksUtils.createPostTaskWithJitter(
endpoint, Service.BACKEND, params, jitterSeconds);
return cloudTasksUtils.createTaskWithJitter(
endpoint,
Action.Method.POST,
RegistryEnvironment.isOnJetty() ? GkeService.BACKEND : GaeService.BACKEND,
params,
jitterSeconds);
}
}

View File

@@ -53,7 +53,7 @@ import google.registry.model.registrar.RegistrarPoc;
import google.registry.model.registrar.RegistrarPocBase;
import google.registry.model.tld.Tld;
import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.Action.GaeService;
import google.registry.request.Header;
import google.registry.request.HttpException.ServiceUnavailableException;
import google.registry.request.Parameter;
@@ -73,7 +73,7 @@ import org.joda.time.Duration;
/** Task that sends domain and host updates to the DNS server. */
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = PublishDnsUpdatesAction.PATH,
method = POST,
automaticallyPrintOk = true,
@@ -328,9 +328,9 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
private void enqueue(ImmutableList<String> domains, ImmutableList<String> hosts) {
cloudTasksUtils.enqueue(
DNS_PUBLISH_PUSH_QUEUE_NAME,
cloudTasksUtils.createPostTask(
PATH,
Service.BACKEND,
cloudTasksUtils.createTask(
this.getClass(),
POST,
ImmutableMultimap.<String, String>builder()
.put(PARAM_TLD, tld)
.put(PARAM_DNS_WRITER, dnsWriter)

View File

@@ -45,7 +45,7 @@ import google.registry.dns.DnsUtils.TargetType;
import google.registry.model.common.DnsRefreshRequest;
import google.registry.model.tld.Tld;
import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
@@ -60,7 +60,7 @@ import org.joda.time.Duration;
* table.
*/
@Action(
service = Service.BACKEND,
service = GaeService.BACKEND,
path = "/_dr/task/readDnsRefreshRequests",
automaticallyPrintOk = true,
method = POST,
@@ -182,9 +182,9 @@ public final class ReadDnsRefreshRequestsAction implements Runnable {
ImmutableList<String> hosts = hostsBuilder.build();
for (String dnsWriter : Tld.get(tld).getDnsWriters()) {
Task task =
cloudTasksUtils.createPostTaskWithJitter(
PublishDnsUpdatesAction.PATH,
Service.BACKEND,
cloudTasksUtils.createTaskWithJitter(
PublishDnsUpdatesAction.class,
POST,
ImmutableMultimap.<String, String>builder()
.put(PARAM_TLD, tld)
.put(PARAM_DNS_WRITER, dnsWriter)

View File

@@ -26,6 +26,7 @@ import google.registry.model.annotations.ExternalMessagingName;
import google.registry.model.domain.Domain;
import google.registry.model.host.Host;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.HttpException.BadRequestException;
import google.registry.request.HttpException.NotFoundException;
import google.registry.request.Parameter;
@@ -35,7 +36,7 @@ import javax.inject.Inject;
/** Action that manually triggers refresh of DNS information. */
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = "/_dr/task/dnsRefresh",
automaticallyPrintOk = true,
auth = Auth.AUTH_ADMIN)

View File

@@ -26,14 +26,18 @@ import google.registry.model.domain.Domain;
import google.registry.model.host.Host;
import google.registry.persistence.VKey;
import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import javax.inject.Inject;
import org.joda.time.DateTime;
@Action(service = Service.BACKEND, path = PATH, method = Action.Method.POST, auth = Auth.AUTH_ADMIN)
@Action(
service = GaeService.BACKEND,
path = PATH,
method = Action.Method.POST,
auth = Auth.AUTH_ADMIN)
public class RefreshDnsOnHostRenameAction implements Runnable {
public static final String QUEUE_HOST_RENAME = "async-host-rename";

View File

@@ -24,9 +24,7 @@
<static-files>
<include path="/*.html" expiration="1m"/>
<include path="/assets/js/**" expiration="1m"/>
<include path="/assets/css/**" expiration="1m"/>
<include path="/assets/images/**" expiration="1m"/>
<include path="/assets/sources/**" expiration="1m"/>
<include path="/registrar/*.html" expiration="1m"/>
</static-files>
</appengine-web-app>

View File

@@ -18,58 +18,6 @@
<url-pattern>/_dr/epp</url-pattern>
</servlet-mapping>
<!-- Registrar Console endpoint, which accepts EPP XHRs from GAE GAIA-authenticated sessions. -->
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registrar-xhr</url-pattern>
</servlet-mapping>
<!-- Registrar Console. -->
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registrar</url-pattern>
</servlet-mapping>
<!-- Registrar creation console. -->
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registrar-create</url-pattern>
</servlet-mapping>
<!-- OT&E creation console. -->
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registrar-ote-setup</url-pattern>
</servlet-mapping>
<!-- OT&E status console. -->
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registrar-ote-status</url-pattern>
</servlet-mapping>
<!-- Registrar Self-serve Settings. -->
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registrar-settings</url-pattern>
</servlet-mapping>
<!-- Registry lock get/post/verify. -->
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registry-lock-get</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registry-lock-post</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registry-lock-verify</url-pattern>
</servlet-mapping>
<!-- Registrar console endpoints -->
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
@@ -84,47 +32,18 @@
Admin-only internal section. Requests for paths covered by the URL patterns below will be
checked for a logged-in user account that's allowed to access the AppEngine admin console
(NOTE: this includes Editor/Viewer permissions in addition to Owner and the new IAM
App Engine Admin role. See https://cloud.google.com/appengine/docs/java/access-control
App Engine Admin role. See https://cloud.google.com/appengine/docs/java/access-control
specifically the "Access handlers that have a login:admin restriction" line.)
TODO(b/28219927): lift some of these restrictions so that we can allow OAuth authentication
for endpoints that need to be accessed by open-source automated processes.
</description>
<!-- Internal AppEngine endpoints. The '_ah' is short for app hosting. -->
<url-pattern>/_ah/*</url-pattern>
<!-- Verbatim JavaScript sources (only visible to admins for debugging). -->
<url-pattern>/assets/sources/*</url-pattern>
<!-- TODO(b/26776367): Move these files to /assets/sources. -->
<url-pattern>/assets/js/registrar_bin.js.map</url-pattern>
<url-pattern>/assets/js/registrar_dbg.js</url-pattern>
<url-pattern>/assets/css/registrar_dbg.css</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
<!-- Repeated here since catch-all rule below is not inherited. -->
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Registrar console</web-resource-name>
<description>
Registrar console requires user login. This is in addition to the
code-level "requireLogin" configuration on individual @Actions.
</description>
<url-pattern>/registrar*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
<!-- Repeated here since catch-all rule below is not inherited. -->
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>

View File

@@ -24,9 +24,6 @@
<static-files>
<include path="/*.html" expiration="1m"/>
<include path="/assets/js/**" expiration="1m"/>
<include path="/assets/css/**" expiration="1m"/>
<include path="/assets/images/**" expiration="1m"/>
<include path="/assets/sources/**" expiration="1m"/>
<include path="/registrar/*.html" expiration="1m"/>
</static-files>
</appengine-web-app>

View File

@@ -28,16 +28,7 @@
<include path="/*.html">
<http-header name="Cache-Control" value="max-age=0,must-revalidate" />
</include>
<include path="/assets/js/**">
<http-header name="Cache-Control" value="max-age=0,must-revalidate" />
</include>
<include path="/assets/css/**">
<http-header name="Cache-Control" value="max-age=0,must-revalidate" />
</include>
<include path="/assets/images/**">
<http-header name="Cache-Control" value="max-age=0,must-revalidate" />
</include>
<include path="/assets/sources/**">
<include path="/registrar/*.html">
<http-header name="Cache-Control" value="max-age=0,must-revalidate" />
</include>
</static-files>

View File

@@ -23,10 +23,7 @@
<static-files>
<include path="/*.html" expiration="1d"/>
<include path="/assets/js/**" expiration="1d"/>
<include path="/assets/css/**" expiration="1d"/>
<include path="/assets/images/**" expiration="1d"/>
<include path="/assets/sources/**" expiration="1d"/>
<include path="/registrar/*.html" expiration="1d"/>
</static-files>
<!-- Prevent uncaught servlet errors from leaking a stack trace. -->

View File

@@ -27,10 +27,7 @@
<static-files>
<include path="/*.html" expiration="1h"/>
<include path="/assets/js/**" expiration="1h"/>
<include path="/assets/css/**" expiration="1h"/>
<include path="/assets/images/**" expiration="1h"/>
<include path="/assets/sources/**" expiration="1h"/>
<include path="/registrar/*.html" expiration="1h"/>
</static-files>
<!-- Prevent uncaught servlet errors from leaking a stack trace. -->

View File

@@ -23,10 +23,7 @@
<static-files>
<include path="/*.html" expiration="1d"/>
<include path="/assets/js/**" expiration="1d"/>
<include path="/assets/css/**" expiration="1d"/>
<include path="/assets/images/**" expiration="1d"/>
<include path="/assets/sources/**" expiration="1d"/>
<include path="/registrar/*.html" expiration="1d"/>
</static-files>
<!-- Prevent uncaught servlet errors from leaking a stack trace. -->

View File

@@ -16,6 +16,8 @@ package google.registry.export;
import static com.google.common.base.Verify.verifyNotNull;
import static google.registry.model.tld.Tlds.getTldsOfType;
import static google.registry.persistence.PersistenceModule.TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ;
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -27,17 +29,26 @@ import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.config.RegistryConfig.Config;
import google.registry.gcs.GcsUtils;
import google.registry.model.common.FeatureFlag;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldType;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.auth.Auth;
import google.registry.storage.drive.DriveConnection;
import google.registry.util.Clock;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.time.Instant;
import java.util.List;
import javax.inject.Inject;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.TupleTransformer;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
/**
* An action that exports the list of active domains on all real TLDs to Google Drive and GCS.
@@ -46,14 +57,28 @@ import javax.inject.Inject;
* name TLD.txt into the domain-lists bucket. Note that this overwrites the files in place.
*/
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = "/_dr/task/exportDomainLists",
method = POST,
auth = Auth.AUTH_ADMIN)
public class ExportDomainListsAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public static final String REGISTERED_DOMAINS_FILENAME = "registered_domains.txt";
private static final String SELECT_DOMAINS_STATEMENT =
"SELECT domainName FROM Domain WHERE tld = :tld AND deletionTime > :now ORDER by domainName";
private static final String SELECT_DOMAINS_AND_DELETION_TIMES_STATEMENT =
"""
SELECT d.domain_name, d.deletion_time, d.statuses, gp.type FROM "Domain" d
LEFT JOIN (SELECT type, domain_repo_id FROM "GracePeriod"
WHERE type = 'REDEMPTION'
AND expiration_time > CAST(:now AS timestamptz)) AS gp
ON d.repo_id = gp.domain_repo_id
WHERE d.tld = :tld
AND d.deletion_time > CAST(:now AS timestamptz)
ORDER BY d.domain_name""";
// This may be a CSV, but it is uses a .txt file extension for back-compatibility
static final String REGISTERED_DOMAINS_FILENAME = "registered_domains.txt";
@Inject Clock clock;
@Inject DriveConnection driveConnection;
@@ -66,46 +91,50 @@ public class ExportDomainListsAction implements Runnable {
public void run() {
ImmutableSet<String> realTlds = getTldsOfType(TldType.REAL);
logger.atInfo().log("Exporting domain lists for TLDs %s.", realTlds);
boolean includeDeletionTimes =
tm().transact(
() ->
FeatureFlag.isActiveNowOrElse(
FeatureFlag.FeatureName.INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS, false));
realTlds.forEach(
tld -> {
List<String> domains =
tm().transact(
() ->
// Note that if we had "creationTime <= :now" in the condition (not
// necessary as there is no pending creation, the order of deletionTime
// and creationTime in the query would have been significant and it
// should come after deletionTime. When Hibernate substitutes "now" it
// will first validate that the **first** field that is to be compared
// with it (deletionTime) is assignable from the substituted Java object
// (click.nowUtc()). Since creationTime is a CreateAutoTimestamp, if it
// comes first, we will need to substitute "now" with
// CreateAutoTimestamp.create(clock.nowUtc()). This might look a bit
// strange as the Java object type is clearly incompatible between the
// two fields deletionTime (DateTime) and creationTime, yet they are
// compared with the same "now". It is actually OK because in the end
// Hibernate converts everything to SQL types (and Java field names to
// SQL column names) to run the query. Both CreateAutoTimestamp and
// DateTime are persisted as timestamp_z in SQL. It is only the
// validation that compares the Java types, and only with the first
// field that compares with the substituted value.
tm().query(
"SELECT domainName FROM Domain "
+ "WHERE tld = :tld "
+ "AND deletionTime > :now "
+ "ORDER by domainName ASC",
String.class)
List<String> domainsList =
replicaTm()
.transact(
TRANSACTION_REPEATABLE_READ,
() -> {
if (includeDeletionTimes) {
// We want to include deletion times, but only for domains in the 5-day
// PENDING_DELETE period after the REDEMPTION grace period. In order to
// accomplish this without loading the entire list of domains, we use a
// native query to join against the GracePeriod table to find
// PENDING_DELETE domains that don't have a REDEMPTION grace period.
return replicaTm()
.getEntityManager()
.createNativeQuery(SELECT_DOMAINS_AND_DELETION_TIMES_STATEMENT)
.unwrap(NativeQuery.class)
.setTupleTransformer(new DomainResultTransformer())
.setParameter("tld", tld)
.setParameter("now", clock.nowUtc())
.getResultList());
String domainsList = Joiner.on("\n").join(domains);
.setParameter("now", replicaTm().getTransactionTime().toString())
.getResultList();
} else {
return replicaTm()
.query(SELECT_DOMAINS_STATEMENT, String.class)
.setParameter("tld", tld)
.setParameter("now", replicaTm().getTransactionTime())
.getResultList();
}
});
logger.atInfo().log(
"Exporting %d domains for TLD %s to GCS and Drive.", domains.size(), tld);
exportToGcs(tld, domainsList, gcsBucket, gcsUtils);
exportToDrive(tld, domainsList, driveConnection);
"Exporting %d domains for TLD %s to GCS and Drive.", domainsList.size(), tld);
String domainsListOutput = Joiner.on('\n').join(domainsList);
exportToGcs(tld, domainsListOutput, gcsBucket, gcsUtils);
exportToDrive(tld, domainsListOutput, driveConnection);
});
}
protected static boolean exportToDrive(
protected static void exportToDrive(
String tldStr, String domains, DriveConnection driveConnection) {
verifyNotNull(driveConnection, "Expecting non-null driveConnection");
try {
@@ -128,12 +157,10 @@ public class ExportDomainListsAction implements Runnable {
} catch (Throwable e) {
logger.atSevere().withCause(e).log(
"Error exporting registered domains for TLD %s to Drive, skipping...", tldStr);
return false;
}
return true;
}
protected static boolean exportToGcs(
protected static void exportToGcs(
String tld, String domains, String gcsBucket, GcsUtils gcsUtils) {
BlobId blobId = BlobId.of(gcsBucket, tld + ".txt");
try (OutputStream gcsOutput = gcsUtils.openOutputStream(blobId);
@@ -142,8 +169,22 @@ public class ExportDomainListsAction implements Runnable {
} catch (Throwable e) {
logger.atSevere().withCause(e).log(
"Error exporting registered domains for TLD %s to GCS, skipping...", tld);
return false;
}
return true;
}
/** Transforms the multiple columns selected from SQL into the output line. */
private static class DomainResultTransformer implements TupleTransformer<String> {
@Override
public String transformTuple(Object[] domainResult, String[] strings) {
String domainName = (String) domainResult[0];
Instant deletionInstant = (Instant) domainResult[1];
DateTime deletionTime = new DateTime(deletionInstant.toEpochMilli(), DateTimeZone.UTC);
String[] domainStatuses = (String[]) domainResult[2];
String gracePeriodType = (String) domainResult[3];
boolean inPendingDelete =
ImmutableSet.copyOf(domainStatuses).contains(StatusValue.PENDING_DELETE.toString())
&& !GracePeriodStatus.REDEMPTION.toString().equals(gracePeriodType);
return String.format("%s,%s", domainName, inPendingDelete ? deletionTime : "");
}
}
}

View File

@@ -33,6 +33,7 @@ import google.registry.model.tld.Tld;
import google.registry.model.tld.label.PremiumList.PremiumEntry;
import google.registry.model.tld.label.PremiumListDao;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.RequestParameters;
import google.registry.request.Response;
@@ -45,7 +46,7 @@ import javax.inject.Inject;
/** Action that exports the premium terms list for a TLD to Google Drive. */
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = "/_dr/task/exportPremiumTerms",
method = POST,
auth = Auth.AUTH_ADMIN)

View File

@@ -25,6 +25,7 @@ import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.model.tld.Tld;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.RequestParameters;
import google.registry.request.Response;
@@ -34,7 +35,7 @@ import javax.inject.Inject;
/** Action that exports the publicly viewable reserved terms list for a TLD to Google Drive. */
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = "/_dr/task/exportReservedTerms",
method = POST,
auth = Auth.AUTH_ADMIN)

View File

@@ -35,6 +35,7 @@ import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.RegistrarPoc;
import google.registry.model.registrar.RegistrarPocBase;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Retrier;
@@ -53,7 +54,7 @@ import javax.inject.Inject;
* <p>This uses the <a href="https://developers.google.com/admin-sdk/directory/">Directory API</a>.
*/
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = "/_dr/task/syncGroupMembers",
method = POST,
auth = Auth.AUTH_ADMIN)

View File

@@ -24,6 +24,7 @@ import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import com.google.common.flogger.FluentLogger;
import google.registry.config.RegistryConfig.Config;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
@@ -54,7 +55,7 @@ import org.joda.time.Duration;
* @see SyncRegistrarsSheet
*/
@Action(
service = Action.Service.BACKEND,
service = GaeService.BACKEND,
path = SyncRegistrarsSheetAction.PATH,
method = POST,
auth = Auth.AUTH_ADMIN)

View File

@@ -32,7 +32,8 @@ import static google.registry.monitoring.whitebox.CheckApiMetric.Status.SUCCESS;
import static google.registry.monitoring.whitebox.CheckApiMetric.Status.UNKNOWN_ERROR;
import static google.registry.monitoring.whitebox.CheckApiMetric.Tier.PREMIUM;
import static google.registry.monitoring.whitebox.CheckApiMetric.Tier.STANDARD;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.persistence.PersistenceModule.TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ;
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
import static google.registry.pricing.PricingEngineProxy.isDomainPremium;
import static google.registry.util.DomainNameUtils.canonicalizeHostname;
import static org.json.simple.JSONValue.toJSONString;
@@ -54,6 +55,7 @@ import google.registry.model.tld.label.ReservationType;
import google.registry.monitoring.whitebox.CheckApiMetric;
import google.registry.monitoring.whitebox.CheckApiMetric.Availability;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.RequestParameters;
import google.registry.request.Response;
@@ -71,7 +73,7 @@ import org.joda.time.DateTime;
* user controlled, lest it open an XSS vector. Do not modify this to return the domain name in the
* response.
*/
@Action(service = Action.Service.PUBAPI, path = "/check", auth = Auth.AUTH_PUBLIC)
@Action(service = GaeService.PUBAPI, path = "/check", auth = Auth.AUTH_PUBLIC)
public class CheckApiAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@@ -108,7 +110,7 @@ public class CheckApiAction implements Runnable {
try {
domainString = canonicalizeHostname(nullToEmpty(domain));
domainName = validateDomainName(domainString);
return tm().transact(() -> checkDomainName(domainName));
return replicaTm().transact(TRANSACTION_REPEATABLE_READ, () -> checkDomainName(domainName));
} catch (IllegalArgumentException | EppException e) {
metricBuilder.status(INVALID_NAME);
return fail("Must supply a valid domain name on an authoritative TLD");
@@ -116,7 +118,7 @@ public class CheckApiAction implements Runnable {
}
private Map<String, Object> checkDomainName(InternetDomainName domainName) {
tm().assertInTransaction();
replicaTm().assertInTransaction();
String domainString;
try {
@@ -130,7 +132,7 @@ public class CheckApiAction implements Runnable {
// Throws an EppException with a reasonable error message which will be sent back to caller.
validateDomainNameWithIdnTables(domainName);
DateTime now = tm().getTransactionTime();
DateTime now = replicaTm().getTransactionTime();
Tld tld = Tld.get(domainName.parent().toString());
try {
verifyNotInPredelegation(tld, now);

View File

@@ -15,6 +15,7 @@
package google.registry.flows;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Action.Method;
import google.registry.request.Payload;
import google.registry.request.auth.Auth;
@@ -26,7 +27,7 @@ import javax.inject.Inject;
* to RFC 5730. Commands must be requested via POST.
*/
@Action(
service = Action.Service.DEFAULT,
service = GaeService.DEFAULT,
path = "/_dr/epp",
method = Method.POST,
auth = Auth.AUTH_ADMIN)

View File

@@ -22,6 +22,7 @@ import dagger.Module;
import dagger.Provides;
import google.registry.model.eppcommon.ProtocolDefinition;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Action.Method;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
@@ -30,7 +31,7 @@ import javax.inject.Inject;
/** Runs EPP commands directly without logging in, verifying an XSRF token from the tool. */
@Action(
service = Action.Service.TOOLS,
service = GaeService.TOOLS,
path = EppToolAction.PATH,
method = Method.POST,
auth = Auth.AUTH_ADMIN)

View File

@@ -105,7 +105,7 @@ public final class ExtensionManager {
}
private static final ImmutableSet<EppRequestSource> ALLOWED_METADATA_EPP_REQUEST_SOURCES =
ImmutableSet.of(EppRequestSource.TOOL, EppRequestSource.BACKEND);
ImmutableSet.of(EppRequestSource.BACKEND, EppRequestSource.CONSOLE, EppRequestSource.TOOL);
private void checkForRestrictedExtensions(
ImmutableSet<Class<? extends CommandExtension>> suppliedExtensions)
@@ -164,8 +164,10 @@ public final class ExtensionManager {
/** Service extension(s) must be declared at login. */
public static class UndeclaredServiceExtensionException extends CommandUseErrorException {
public UndeclaredServiceExtensionException(Set<String> undeclaredUris) {
super(String.format("Service extension(s) must be declared at login: %s",
Joiner.on(", ").join(undeclaredUris)));
super(
String.format(
"Service extension(s) must be declared at login: %s",
Joiner.on(", ").join(undeclaredUris)));
}
}

View File

@@ -75,7 +75,8 @@ public class FlowRunner {
flowReporter.recordToLogs();
}
eppMetricBuilder.setCommandNameFromFlow(flowClass.getSimpleName());
if (!isTransactional) {
// We may already be in a transaction, e.g., when invoked by DeleteExpiredDomainsAction.
if (!isTransactional || jpaTransactionManager.inTransaction()) {
return EppOutput.create(flowProvider.get().run());
}
try {

View File

@@ -44,7 +44,9 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import google.registry.batch.AsyncTaskEnqueuer;
import google.registry.config.RegistryConfig;
import google.registry.flows.EppException;
import google.registry.flows.EppException.AssociationProhibitsOperationException;
import google.registry.flows.ExtensionManager;
@@ -117,6 +119,8 @@ import org.joda.time.Duration;
@ReportingSpec(ActivityReportField.DOMAIN_DELETE)
public final class DomainDeleteFlow implements MutatingFlow {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
StatusValue.CLIENT_DELETE_PROHIBITED,
StatusValue.PENDING_DELETE,
@@ -212,10 +216,17 @@ public final class DomainDeleteFlow implements MutatingFlow {
// superuser (i.e. the registrar didn't request this delete and thus should be notified even if
// it is synchronous).
if (durationUntilDelete.isLongerThan(Duration.ZERO) || isSuperuser) {
PollMessage.OneTime deletePollMessage =
createDeletePollMessage(existingDomain, domainHistoryId, deletionTime);
entitiesToSave.add(deletePollMessage);
builder.setDeletePollMessage(deletePollMessage.createVKey());
if (RegistryConfig.getNoPollMessageOnDeletionRegistrarIds()
.contains(existingDomain.getCurrentSponsorRegistrarId())) {
logger.atInfo().log(
"Skipping poll message on domain deletion for registrar %s due to configuration",
existingDomain.getCurrentSponsorRegistrarId());
} else {
PollMessage.OneTime deletePollMessage =
createDeletePollMessage(existingDomain, domainHistoryId, deletionTime);
entitiesToSave.add(deletePollMessage);
builder.setDeletePollMessage(deletePollMessage.createVKey());
}
}
// Send a second poll message immediately if the domain is being deleted asynchronously by a

View File

@@ -95,7 +95,7 @@ public final class DomainPricingLogic {
false, tld.getCreateBillingCost(dateTime), domainPrices.getRenewCost());
}
Money domainCreateCost =
getDomainCreateCostWithDiscount(domainPrices, years, allocationToken);
getDomainCreateCostWithDiscount(domainPrices, years, allocationToken, tld);
// Apply a sunrise discount if configured and applicable
if (isSunriseCreate) {
domainCreateCost =
@@ -134,7 +134,8 @@ public final class DomainPricingLogic {
int years,
@Nullable BillingRecurrence billingRecurrence,
Optional<AllocationToken> allocationToken)
throws AllocationTokenInvalidForPremiumNameException {
throws AllocationTokenInvalidForCurrencyException,
AllocationTokenInvalidForPremiumNameException {
checkArgument(years > 0, "Number of years must be positive");
Money renewCost;
DomainPrices domainPrices = getPricesForDomainName(domainName, dateTime);
@@ -172,7 +173,8 @@ public final class DomainPricingLogic {
years,
allocationToken,
tld.getStandardRenewCost(dateTime),
Optional.empty());
Optional.empty(),
tld);
isRenewCostPremiumPrice = false;
}
default ->
@@ -262,14 +264,15 @@ public final class DomainPricingLogic {
/** Returns the domain create cost with allocation-token-related discounts applied. */
private Money getDomainCreateCostWithDiscount(
DomainPrices domainPrices, int years, Optional<AllocationToken> allocationToken)
DomainPrices domainPrices, int years, Optional<AllocationToken> allocationToken, Tld tld)
throws EppException {
return getDomainCostWithDiscount(
domainPrices.isPremium(),
years,
allocationToken,
domainPrices.getCreateCost(),
Optional.of(domainPrices.getRenewCost()));
Optional.of(domainPrices.getRenewCost()),
tld);
}
/** Returns the domain renew cost with allocation-token-related discounts applied. */
@@ -279,7 +282,8 @@ public final class DomainPricingLogic {
DateTime dateTime,
int years,
Optional<AllocationToken> allocationToken)
throws AllocationTokenInvalidForPremiumNameException {
throws AllocationTokenInvalidForCurrencyException,
AllocationTokenInvalidForPremiumNameException {
// Short-circuit if the user sent an anchor-tenant or otherwise NONPREMIUM-renewal token
if (allocationToken.isPresent()) {
AllocationToken token = allocationToken.get();
@@ -293,7 +297,8 @@ public final class DomainPricingLogic {
years,
allocationToken,
domainPrices.getRenewCost(),
Optional.empty());
Optional.empty(),
tld);
}
/**
@@ -310,8 +315,10 @@ public final class DomainPricingLogic {
int years,
Optional<AllocationToken> allocationToken,
Money firstYearCost,
Optional<Money> subsequentYearCost)
throws AllocationTokenInvalidForPremiumNameException {
Optional<Money> subsequentYearCost,
Tld tld)
throws AllocationTokenInvalidForCurrencyException,
AllocationTokenInvalidForPremiumNameException {
checkArgument(years > 0, "Registration years to get cost for must be positive.");
validateTokenForPossiblePremiumName(allocationToken, isPremium);
Money totalDomainFlowCost =
@@ -320,13 +327,31 @@ public final class DomainPricingLogic {
// Apply the allocation token discount, if applicable.
if (allocationToken.isPresent()
&& allocationToken.get().getTokenBehavior().equals(TokenBehavior.DEFAULT)) {
int discountedYears = Math.min(years, allocationToken.get().getDiscountYears());
if (discountedYears > 0) {
var discount =
firstYearCost
.plus(subsequentYearCost.orElse(firstYearCost).multipliedBy(discountedYears - 1))
.multipliedBy(allocationToken.get().getDiscountFraction(), RoundingMode.HALF_EVEN);
totalDomainFlowCost = totalDomainFlowCost.minus(discount);
if (allocationToken.get().getDiscountPrice().isPresent()) {
if (!tld.getCurrency()
.equals(allocationToken.get().getDiscountPrice().get().getCurrencyUnit())) {
throw new AllocationTokenInvalidForCurrencyException();
}
int nonDiscountedYears = Math.max(0, years - allocationToken.get().getDiscountYears());
totalDomainFlowCost =
allocationToken
.get()
.getDiscountPrice()
.get()
.multipliedBy(allocationToken.get().getDiscountYears())
.plus(subsequentYearCost.orElse(firstYearCost).multipliedBy(nonDiscountedYears));
} else {
// Assumes token has discount fraction set.
int discountedYears = Math.min(years, allocationToken.get().getDiscountYears());
if (discountedYears > 0) {
var discount =
firstYearCost
.plus(subsequentYearCost.orElse(firstYearCost).multipliedBy(discountedYears - 1))
.multipliedBy(
allocationToken.get().getDiscountFraction(), RoundingMode.HALF_EVEN);
totalDomainFlowCost = totalDomainFlowCost.minus(discount);
}
}
}
return totalDomainFlowCost;
@@ -339,4 +364,10 @@ public final class DomainPricingLogic {
super("Token not valid for premium name");
}
}
public static class AllocationTokenInvalidForCurrencyException extends CommandUseErrorException {
public AllocationTokenInvalidForCurrencyException() {
super("Token and domain currencies do not match.");
}
}
}

View File

@@ -183,7 +183,9 @@ public final class DomainRestoreRequestFlow implements MutatingFlow {
DomainHistory domainHistory = buildDomainHistory(newDomain, now);
entitiesToSave.add(newDomain, domainHistory, autorenewEvent, autorenewPollMessage);
tm().putAll(entitiesToSave.build());
tm().delete(existingDomain.getDeletePollMessage());
if (existingDomain.getDeletePollMessage() != null) {
tm().delete(existingDomain.getDeletePollMessage());
}
requestDomainDnsRefresh(existingDomain.getDomainName());
return responseBuilder
.setExtensions(createResponseExtensions(feesAndCredits, feeUpdate, isExpired))

View File

@@ -156,7 +156,7 @@ public class AllocationTokenFlowUtils {
Optional<AllocationToken> token, boolean isPremium)
throws AllocationTokenInvalidForPremiumNameException {
if (token.isPresent()
&& token.get().getDiscountFraction() != 0.0
&& (token.get().getDiscountFraction() != 0.0 || token.get().getDiscountPrice().isPresent())
&& isPremium
&& !token.get().shouldDiscountPremiums()) {
throw new AllocationTokenInvalidForPremiumNameException();
@@ -177,8 +177,9 @@ public class AllocationTokenFlowUtils {
return maybeTokenEntity.get();
}
// TODO(b/368069206): `reTransact` needed by tests only.
maybeTokenEntity =
tm().transact(() -> tm().loadByKeyIfPresent(VKey.create(AllocationToken.class, token)));
tm().reTransact(() -> tm().loadByKeyIfPresent(VKey.create(AllocationToken.class, token)));
if (maybeTokenEntity.isEmpty()) {
throw new InvalidAllocationTokenException();
@@ -287,6 +288,7 @@ public class AllocationTokenFlowUtils {
super("Alloc token not in promo period");
}
}
/** The allocation token is not valid for this TLD. */
public static class AllocationTokenNotValidForTldException
extends AssociationProhibitsOperationException {

View File

@@ -65,7 +65,7 @@ import google.registry.model.host.HostCommand.Update.Change;
import google.registry.model.host.HostHistory;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.persistence.VKey;
import google.registry.request.Action.Service;
import google.registry.request.Action;
import java.util.Objects;
import java.util.Optional;
import javax.inject.Inject;
@@ -277,9 +277,9 @@ public final class HostUpdateFlow implements MutatingFlow {
// We must also enqueue updates for all domains that use this host as their nameserver so
// that their NS records can be updated to point at the new name.
Task task =
cloudTasksUtils.createPostTask(
RefreshDnsOnHostRenameAction.PATH,
Service.BACKEND,
cloudTasksUtils.createTask(
RefreshDnsOnHostRenameAction.class,
Action.Method.POST,
ImmutableMultimap.of(PARAM_HOST_KEY, existingHost.createVKey().stringify()));
cloudTasksUtils.enqueue(QUEUE_HOST_RENAME, task);
}

View File

@@ -37,6 +37,8 @@ import google.registry.model.poll.MessageQueueInfo;
import google.registry.model.poll.PollMessage;
import google.registry.model.poll.PollMessageExternalKeyConverter;
import google.registry.model.poll.PollMessageExternalKeyConverter.PollMessageExternalKeyParseException;
import google.registry.persistence.IsolationLevel;
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
import google.registry.persistence.VKey;
import java.util.Optional;
import javax.inject.Inject;
@@ -55,6 +57,7 @@ import org.joda.time.DateTime;
* @error {@link PollAckFlow.MissingMessageIdException}
* @error {@link PollAckFlow.NotAuthorizedToAckMessageException}
*/
@IsolationLevel(value = TransactionIsolationLevel.TRANSACTION_READ_COMMITTED)
public final class PollAckFlow implements MutatingFlow {
@Inject ExtensionManager extensionManager;

View File

@@ -32,6 +32,8 @@ import google.registry.model.eppoutput.EppResponse;
import google.registry.model.poll.MessageQueueInfo;
import google.registry.model.poll.PollMessage;
import google.registry.model.poll.PollMessageExternalKeyConverter;
import google.registry.persistence.IsolationLevel;
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
import java.util.Optional;
import javax.inject.Inject;
import org.joda.time.DateTime;
@@ -47,6 +49,7 @@ import org.joda.time.DateTime;
*
* @error {@link PollRequestFlow.UnexpectedMessageIdException}
*/
@IsolationLevel(value = TransactionIsolationLevel.TRANSACTION_READ_COMMITTED)
public final class PollRequestFlow implements TransactionalFlow {
@Inject ExtensionManager extensionManager;

View File

@@ -29,8 +29,9 @@ import com.google.common.collect.Iterators;
import com.google.common.flogger.FluentLogger;
import com.google.protobuf.Timestamp;
import google.registry.batch.CloudTasksUtils;
import google.registry.flows.EppToolAction;
import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.security.XsrfTokenManager;
@@ -54,7 +55,7 @@ import org.joda.time.DateTime;
* least one must be specified in order for load testing to do anything.
*/
@Action(
service = Action.Service.TOOLS,
service = GaeService.TOOLS,
path = LoadTestAction.PATH,
method = Action.Method.POST,
automaticallyPrintOk = true,
@@ -335,9 +336,9 @@ public class LoadTestAction implements Runnable {
Task.newBuilder()
.setAppEngineHttpRequest(
cloudTasksUtils
.createPostTask(
"/_dr/epptool",
Service.TOOLS,
.createTask(
EppToolAction.class,
Action.Method.POST,
ImmutableMultimap.of(
"clientId",
registrarId,

View File

@@ -345,7 +345,7 @@ public final class EppResourceUtils {
"key must be either VKey<Contact> or VKey<Host>, but it is %s",
key);
boolean isContactKey = key.getKind().equals(Contact.class);
return tm().transact(
return tm().reTransact(
() -> {
Query query;
if (isContactKey) {

View File

@@ -66,7 +66,7 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
TEST_FEATURE,
MINIMUM_DATASET_CONTACTS_OPTIONAL,
MINIMUM_DATASET_CONTACTS_PROHIBITED,
NEW_CONSOLE
INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS
}
/** The name of the flag/feature. */
@@ -82,7 +82,7 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
TimedTransitionProperty.withInitialValue(FeatureStatus.INACTIVE);
public static Optional<FeatureFlag> getUncached(FeatureName featureName) {
return tm().transact(() -> tm().loadByKeyIfPresent(createVKey(featureName)));
return tm().reTransact(() -> tm().loadByKeyIfPresent(createVKey(featureName)));
}
public static ImmutableList<FeatureFlag> getAllUncached() {
@@ -155,6 +155,15 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
return status.getValueAtTime(time);
}
/** Returns if the flag is active, or the default value if the flag does not exist. */
public static boolean isActiveNowOrElse(FeatureName featureName, boolean defaultValue) {
tm().assertInTransaction();
return CACHE
.get(featureName)
.map(flag -> flag.getStatus(tm().getTransactionTime()).equals(ACTIVE))
.orElse(defaultValue);
}
/** Returns if the FeatureFlag with the given FeatureName is active now. */
public static boolean isActiveNow(FeatureName featureName) {
tm().assertInTransaction();

View File

@@ -185,4 +185,9 @@ public class TimedTransitionProperty<V extends Serializable> implements UnsafeSe
public int hashCode() {
return this.backingMap.hashCode();
}
@Override
public String toString() {
return this.backingMap.toString();
}
}

View File

@@ -24,7 +24,7 @@ import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.batch.CloudTasksUtils;
import google.registry.persistence.VKey;
import google.registry.request.Action.Service;
import google.registry.request.Action;
import google.registry.tools.IamClient;
import google.registry.tools.ServiceConnection;
import google.registry.tools.server.UpdateUserGroupAction;
@@ -126,9 +126,9 @@ public class User extends UserBase {
CloudTasksUtils cloudTasksUtils,
Mode mode) {
Task task =
cloudTasksUtils.createPostTask(
UpdateUserGroupAction.PATH,
Service.TOOLS,
cloudTasksUtils.createTask(
UpdateUserGroupAction.class,
Action.Method.POST,
ImmutableMultimap.of(
"userEmailAddress",
userEmailAddress,

View File

@@ -22,6 +22,7 @@ import static google.registry.util.PasswordUtils.SALT_SUPPLIER;
import static google.registry.util.PasswordUtils.hashPassword;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.gson.annotations.Expose;
import google.registry.model.Buildable;
import google.registry.model.UpdateAutoTimestampEntity;
import google.registry.util.PasswordUtils;
@@ -50,12 +51,13 @@ public class UserBase extends UpdateAutoTimestampEntity implements Buildable {
private static final long serialVersionUID = 6936728603828566721L;
/** Email address of the user in question. */
@Transient String emailAddress;
@Transient @Expose String emailAddress;
/** Optional external email address to use for registry lock confirmation emails. */
@Column String registryLockEmailAddress;
/** Roles (which grant permissions) associated with this user. */
@Expose
@Column(nullable = false)
UserRoles userRoles;

View File

@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.collect.ImmutableMap;
import com.google.gson.annotations.Expose;
import google.registry.model.Buildable;
import google.registry.model.ImmutableObject;
import google.registry.persistence.converter.RegistrarToRoleMapUserType;
@@ -53,6 +54,7 @@ public class UserRoles extends ImmutableObject implements Buildable {
private GlobalRole globalRole = GlobalRole.NONE;
/** Any per-registrar roles that this user may have. */
@Expose
@Type(RegistrarToRoleMapUserType.class)
private Map<String, RegistrarRole> registrarRoles = ImmutableMap.of();

View File

@@ -579,7 +579,7 @@ public class DomainBase extends EppResource
/** Loads and returns the fully qualified host names of all linked nameservers. */
public ImmutableSortedSet<String> loadNameserverHostNames() {
return tm().transact(
return tm().reTransact(
() ->
tm().loadByKeys(getNameservers()).values().stream()
.map(Host::getHostName)

View File

@@ -123,8 +123,8 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
* Bypasses the premium list to use the standard creation price. Does not affect the renewal
* price.
*
* <p>This cannot be specified along with a discount fraction, and any renewals (automatic or
* otherwise) will use the premium price for the domain if one exists.
* <p>This cannot be specified along with a discount fraction/price, and any renewals (automatic
* or otherwise) will use the premium price for the domain if one exists.
*
* <p>Tokens with this behavior must be tied to a single particular domain.
*/
@@ -248,6 +248,22 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
@AttributeOverride(name = "currency", column = @Column(name = "renewalPriceCurrency"))
Money renewalPrice;
/**
* A discount that allows the setting of promotional prices. This field is different from {@code
* discountFraction} because the price set here is treated as the domain price, versus {@code
* discountFraction} that applies a fraction discount to the domain base price.
*
* <p>Prefer this method of discount when attempting to set a promotional price across TLDs with
* different base prices.
*/
@Nullable
@AttributeOverride(
name = "amount",
// Override Hibernate default (numeric(38,2)) to match real schema definition (numeric(19,2)).
column = @Column(name = "discountPriceAmount", precision = 19, scale = 2))
@AttributeOverride(name = "currency", column = @Column(name = "discountPriceCurrency"))
Money discountPrice;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
RegistrationBehavior registrationBehavior = RegistrationBehavior.DEFAULT;
@@ -299,6 +315,10 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
return discountFraction;
}
public Optional<Money> getDiscountPrice() {
return Optional.ofNullable(discountPrice);
}
public boolean shouldDiscountPremiums() {
return discountPremiums;
}
@@ -406,8 +426,10 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
getInstance().discountFraction > 0 || !getInstance().discountPremiums,
"Discount premiums can only be specified along with a discount fraction");
checkArgument(
getInstance().discountFraction > 0 || getInstance().discountYears == 1,
"Discount years can only be specified along with a discount fraction");
getInstance().discountFraction > 0
|| getInstance().discountPrice != null
|| getInstance().discountYears == 1,
"Discount years can only be specified along with a discount fraction/price");
if (getInstance().getTokenType().equals(REGISTER_BSA)) {
checkArgumentNotNull(
getInstance().domainName, "REGISTER_BSA tokens must be tied to a domain");
@@ -418,7 +440,7 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
}
if (getInstance().registrationBehavior.equals(RegistrationBehavior.NONPREMIUM_CREATE)) {
checkArgument(
getInstance().discountFraction == 0.0,
getInstance().discountFraction == 0.0 && getInstance().discountPrice == null,
"NONPREMIUM_CREATE tokens cannot apply a discount");
checkArgumentNotNull(
getInstance().domainName, "NONPREMIUM_CREATE tokens must be tied to a domain");
@@ -454,6 +476,12 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
"BULK_PRICING tokens must have exactly one allowed client registrar");
}
if (getInstance().discountFraction != 0.0) {
checkArgument(
getInstance().discountPrice == null,
"discountFraction and discountPrice can't be set together");
}
if (getInstance().domainName != null) {
try {
DomainFlowUtils.validateDomainName(getInstance().domainName);
@@ -559,5 +587,10 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
getInstance().registrationBehavior = registrationBehavior;
return this;
}
public Builder setDiscountPrice(@Nullable Money discountPrice) {
getInstance().discountPrice = discountPrice;
return this;
}
}
}

View File

@@ -1014,7 +1014,7 @@ public class RegistrarBase extends UpdateAutoTimestampEntity implements Buildabl
/** Loads and returns a registrar entity by its id directly from the database. */
public static Optional<Registrar> loadByRegistrarId(String registrarId) {
checkArgument(!Strings.isNullOrEmpty(registrarId), "registrarId must be specified");
return tm().transact(() -> tm().loadByKeyIfPresent(createVKey(registrarId)));
return tm().reTransact(() -> tm().loadByKeyIfPresent(createVKey(registrarId)));
}
/**

View File

@@ -172,19 +172,16 @@ public class RegistrarPocBase extends ImmutableObject implements Jsonifiable, Un
*/
public static void updateContacts(
final Registrar registrar, final ImmutableSet<RegistrarPoc> contacts) {
tm().transact(
() -> {
ImmutableSet<String> emailAddressesToKeep =
contacts.stream().map(RegistrarPoc::getEmailAddress).collect(toImmutableSet());
tm().query(
"DELETE FROM RegistrarPoc WHERE registrarId = :registrarId AND "
+ "emailAddress NOT IN :emailAddressesToKeep")
.setParameter("registrarId", registrar.getRegistrarId())
.setParameter("emailAddressesToKeep", emailAddressesToKeep)
.executeUpdate();
ImmutableSet<String> emailAddressesToKeep =
contacts.stream().map(RegistrarPoc::getEmailAddress).collect(toImmutableSet());
tm().query(
"DELETE FROM RegistrarPoc WHERE registrarId = :registrarId AND "
+ "emailAddress NOT IN :emailAddressesToKeep")
.setParameter("registrarId", registrar.getRegistrarId())
.setParameter("emailAddressesToKeep", emailAddressesToKeep)
.executeUpdate();
tm().putAll(contacts);
});
tm().putAll(contacts);
}
public String getName() {

View File

@@ -118,7 +118,7 @@ public class HistoryEntryDao {
/** Loads all history objects from all time from the given registrars. */
public static Iterable<HistoryEntry> loadHistoryObjectsByRegistrars(
ImmutableCollection<String> registrarIds) {
return tm().transact(
return tm().reTransact(
() ->
Streams.concat(
loadHistoryObjectByRegistrarsInternal(ContactHistory.class, registrarIds),

View File

@@ -39,7 +39,8 @@ public final class TmchCrl extends CrossTldSingleton {
/** Returns the singleton instance of this entity, without memoization. */
public static Optional<TmchCrl> get() {
return tm().transact(() -> tm().loadSingleton(TmchCrl.class));
// TODO(b/368069206): move transaction up to `TmchCertificateAuthority#updateCrl`
return tm().reTransact(() -> tm().loadSingleton(TmchCrl.class));
}
/**

View File

@@ -102,11 +102,9 @@ interface RegistryComponent {
class RegistryModule {
@Provides
static RequestHandler<RequestComponent> provideRequestHandler(
@Config("baseDomain") String baseDomain,
Provider<RequestComponent.Builder> componentProvider,
RequestAuthenticator requestAuthenticator) {
return RequestHandler.create(
RequestComponent.class, baseDomain, componentProvider, requestAuthenticator);
return RequestHandler.create(RequestComponent.class, componentProvider, requestAuthenticator);
}
}
}

View File

@@ -119,6 +119,7 @@ import google.registry.ui.server.console.ConsoleRegistryLockAction;
import google.registry.ui.server.console.ConsoleRegistryLockVerifyAction;
import google.registry.ui.server.console.ConsoleUpdateRegistrarAction;
import google.registry.ui.server.console.ConsoleUserDataAction;
import google.registry.ui.server.console.ConsoleUsersAction;
import google.registry.ui.server.console.RegistrarsAction;
import google.registry.ui.server.console.settings.ContactAction;
import google.registry.ui.server.console.settings.SecurityAction;
@@ -189,6 +190,8 @@ interface RequestComponent {
ConsoleUserDataAction consoleUserDataAction();
ConsoleUsersAction consoleUsersAction();
ConsoleDumDownloadAction consoleDumDownloadAction();
ContactAction contactAction();

View File

@@ -35,18 +35,11 @@ import google.registry.ui.server.console.ConsoleRegistryLockAction;
import google.registry.ui.server.console.ConsoleRegistryLockVerifyAction;
import google.registry.ui.server.console.ConsoleUpdateRegistrarAction;
import google.registry.ui.server.console.ConsoleUserDataAction;
import google.registry.ui.server.console.ConsoleUsersAction;
import google.registry.ui.server.console.RegistrarsAction;
import google.registry.ui.server.console.settings.ContactAction;
import google.registry.ui.server.console.settings.SecurityAction;
import google.registry.ui.server.console.settings.WhoisRegistrarFieldsAction;
import google.registry.ui.server.registrar.ConsoleOteSetupAction;
import google.registry.ui.server.registrar.ConsoleRegistrarCreatorAction;
import google.registry.ui.server.registrar.ConsoleUiAction;
import google.registry.ui.server.registrar.OteStatusAction;
import google.registry.ui.server.registrar.RegistrarSettingsAction;
import google.registry.ui.server.registrar.RegistryLockGetAction;
import google.registry.ui.server.registrar.RegistryLockPostAction;
import google.registry.ui.server.registrar.RegistryLockVerifyAction;
/** Dagger component with per-request lifetime for "default" App Engine module. */
@RequestScope
@@ -68,36 +61,28 @@ public interface FrontendRequestComponent {
ConsoleOteAction consoleOteAction();
ConsoleOteSetupAction consoleOteSetupAction();
ConsoleRegistrarCreatorAction consoleRegistrarCreatorAction();
ConsoleRegistryLockAction consoleRegistryLockAction();
ConsoleRegistryLockVerifyAction consoleRegistryLockVerifyAction();
ConsoleUiAction consoleUiAction();
ConsoleUpdateRegistrarAction consoleUpdateRegistrarAction();
ConsoleUserDataAction consoleUserDataAction();
ConsoleUsersAction consoleUsersAction();
ConsoleDumDownloadAction consoleDumDownloadAction();
ContactAction contactAction();
EppTlsAction eppTlsAction();
FlowComponent.Builder flowComponentBuilder();
OteStatusAction oteStatusAction();
RegistrarsAction registrarsAction();
RegistrarSettingsAction registrarSettingsAction();
RegistryLockGetAction registryLockGetAction();
RegistryLockPostAction registryLockPostAction();
RegistryLockVerifyAction registryLockVerifyAction();
SecurityAction securityAction();
WhoisRegistrarFieldsAction whoisRegistrarFieldsAction();
@Subcomponent.Builder

View File

@@ -0,0 +1,154 @@
// 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.persistence.transaction;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.persistence.PersistenceModule.TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.common.collect.UnmodifiableIterator;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.metamodel.EntityType;
import java.util.Optional;
import java.util.stream.Stream;
/** Helper for querying large data sets in batches. */
public final class BatchedQueries {
private BatchedQueries() {}
private static final int DEFAULT_BATCH_SIZE = 500;
public static <T> Stream<ImmutableList<T>> loadAllOf(Class<T> entityType) {
return loadAllOf(entityType, DEFAULT_BATCH_SIZE);
}
public static <T> Stream<ImmutableList<T>> loadAllOf(Class<T> entityType, int batchSize) {
return loadAllOf(tm(), entityType, batchSize);
}
/**
* Loads all entities of type {@code T} in batches.
*
* <p>This method must not be nested in any transaction; same for the traversal of the returned
* {@link Stream}. Each batch is loaded in a separate transaction at the {@code
* TRANSACTION_REPEATABLE_READ} isolation level, and loads the snapshot of the batch at the
* batch's start time. New insertions or updates since then are not reflected in the result.
*/
public static <T> Stream<ImmutableList<T>> loadAllOf(
JpaTransactionManager jpaTm, Class<T> entityType, int batchSize) {
checkState(!jpaTm.inTransaction(), "loadAllOf cannot be nested in a transaction");
checkArgument(batchSize > 0, "batchSize must be positive");
EntityType<T> jpaEntityType = jpaTm.getMetaModel().entity(entityType);
if (!jpaEntityType.hasSingleIdAttribute()) {
// We should support multi-column primary keys on a case-by-case basis.
throw new UnsupportedOperationException(
"Types with multi-column primary key not supported yet");
}
return Streams.stream(
new BatchedIterator<>(new SingleColIdBatchQuery<>(jpaTm, jpaEntityType), batchSize));
}
public interface BatchQuery<T> {
ImmutableList<T> readBatch(Optional<T> lastRead, int batchSize);
}
private static class SingleColIdBatchQuery<T> implements BatchQuery<T> {
private final JpaTransactionManager jpaTm;
private final Class<T> entityType;
private final String initialJpqlQuery;
private final String subsequentJpqlTemplate;
private SingleColIdBatchQuery(JpaTransactionManager jpaTm, EntityType<T> jpaEntityType) {
checkArgument(
jpaEntityType.hasSingleIdAttribute(),
"%s must have a single ID attribute",
jpaEntityType.getJavaType().getSimpleName());
this.jpaTm = jpaTm;
this.entityType = jpaEntityType.getJavaType();
var idAttr = jpaEntityType.getId(jpaEntityType.getIdType().getJavaType());
this.initialJpqlQuery =
String.format("FROM %s ORDER BY %s", jpaEntityType.getName(), idAttr.getName());
this.subsequentJpqlTemplate =
String.format(
"FROM %1$s WHERE %2$s > :id ORDER BY %2$s",
jpaEntityType.getName(), idAttr.getName());
}
@Override
public ImmutableList<T> readBatch(Optional<T> lastRead, int batchSize) {
checkState(!jpaTm.inTransaction(), "Stream cannot be accessed in a transaction");
return jpaTm.transact(
TRANSACTION_REPEATABLE_READ,
() -> {
var entityManager = jpaTm.getEntityManager();
Optional<Object> lastReadId =
lastRead.map(
entityManager.getEntityManagerFactory().getPersistenceUnitUtil()
::getIdentifier);
TypedQuery<T> query =
lastRead.isEmpty()
? entityManager.createQuery(initialJpqlQuery, entityType)
: entityManager
.createQuery(subsequentJpqlTemplate, entityType)
.setParameter("id", lastReadId.get());
var results = ImmutableList.copyOf(query.setMaxResults(batchSize).getResultList());
results.forEach(entityManager::detach);
return results;
});
}
}
private static class BatchedIterator<T> extends UnmodifiableIterator<ImmutableList<T>> {
private final BatchQuery<T> batchQuery;
private final int batchSize;
private ImmutableList<T> cachedBatch = null;
private BatchedIterator(BatchQuery<T> batchQuery, int batchSize) {
this.batchQuery = batchQuery;
this.batchSize = batchSize;
this.cachedBatch = readNextBatch();
}
@Override
public boolean hasNext() {
return !cachedBatch.isEmpty();
}
@Override
public ImmutableList<T> next() {
var toReturn = cachedBatch;
cachedBatch = cachedBatch.size() < batchSize ? ImmutableList.of() : readNextBatch();
return toReturn;
}
private ImmutableList<T> readNextBatch() {
Optional<T> lastRead =
cachedBatch == null
? Optional.empty()
: Optional.ofNullable(Iterables.getLast(cachedBatch, null));
return batchQuery.readBatch(lastRead, batchSize);
}
}
}

View File

@@ -1,42 +0,0 @@
// Copyright 2021 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package google.registry.persistence.transaction;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import java.util.concurrent.atomic.AtomicLong;
/**
* Allocates a {@code long} to use as a {@code @Id}, (part) of the primary SQL key for an entity.
*/
final class IdService {
private IdService() {}
/**
* A SQL Sequence based ID allocator that generates an ID from a monotonically increasing {@link
* AtomicLong}
*
* <p>The generated IDs are project-wide unique.
*/
static long allocateId() {
return tm().transact(
() ->
(Long)
tm().getEntityManager()
.createNativeQuery("SELECT nextval('project_wide_unique_id_seq')")
.getSingleResult());
}
}

View File

@@ -20,6 +20,7 @@ import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.metamodel.Metamodel;
/** Sub-interface of {@link TransactionManager} which defines JPA related methods. */
public interface JpaTransactionManager extends TransactionManager {
@@ -31,6 +32,9 @@ public interface JpaTransactionManager extends TransactionManager {
*/
EntityManager getStandaloneEntityManager();
/** Returns the JPA {@link Metamodel}. */
Metamodel getMetaModel();
/**
* Returns the {@link EntityManager} for the current request.
*

View File

@@ -55,6 +55,7 @@ import jakarta.persistence.TemporalType;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.metamodel.EntityType;
import jakarta.persistence.metamodel.Metamodel;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
@@ -70,6 +71,7 @@ import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@@ -115,6 +117,11 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
return emf.createEntityManager();
}
@Override
public Metamodel getMetaModel() {
return this.emf.getMetamodel();
}
@Override
public EntityManager getEntityManager() {
assertInTransaction();
@@ -224,7 +231,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
EntityTransaction txn = txnInfo.entityManager.getTransaction();
try {
txn.begin();
txnInfo.start(clock, readOnly ? ReplicaDbIdService::allocatedId : IdService::allocateId);
txnInfo.start(clock, readOnly ? ReplicaDbIdService::allocateId : this::fetchIdFromSequence);
if (readOnly) {
getEntityManager().createNativeQuery("SET TRANSACTION READ ONLY").executeUpdate();
logger.atInfo().log("Using read-only SQL replica");
@@ -558,6 +565,19 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
return emf.getMetamodel().entity(clazz);
}
/**
* A SQL Sequence based ID allocator that generates an ID from a monotonically increasing {@link
* AtomicLong}
*
* <p>The generated IDs are project-wide unique.
*/
private long fetchIdFromSequence() {
return (Long)
getEntityManager()
.createNativeQuery("SELECT nextval('project_wide_unique_id_seq')")
.getSingleResult();
}
private record EntityId(String name, Object value) {}
private static ImmutableSet<EntityId> getEntityIdsFromEntity(
@@ -1038,4 +1058,23 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
.collect(toImmutableList());
}
}
/**
* Provides {@code long} values for use as {@code id} by JPA model entities in (read-only)
* transactions in the replica database. Each id is only unique in the JVM instance.
*
* <p>The {@link #fetchIdFromSequence database sequence-based id allocator} cannot be used with
* the replica because id generation is a write operation.
*/
private static final class ReplicaDbIdService {
private static final AtomicLong nextId = new AtomicLong(1);
/**
* Returns the next long value from a {@link AtomicLong}. Each id is unique in the JVM instance.
*/
static long allocateId() {
return nextId.getAndIncrement();
}
}
}

Some files were not shown because too many files have changed in this diff Show More