Merge pull request 'Mapfix Release' (#264) from mapfix-release into staging
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #264
This commit was merged in pull request #264.
This commit is contained in:
96
Cargo.lock
generated
96
Cargo.lock
generated
@@ -56,9 +56,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.98"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
||||
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
@@ -266,9 +266,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.31"
|
||||
version = "1.2.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2"
|
||||
checksum = "2352e5597e9c544d5e6d9c95190d5d27738ade584fa8db0a16e130e5c2b5296e"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
@@ -640,9 +640,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.11"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785"
|
||||
checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
@@ -659,9 +659,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.4"
|
||||
version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
@@ -784,7 +784,7 @@ dependencies = [
|
||||
"libc",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"socket2 0.6.0",
|
||||
"socket2 0.5.10",
|
||||
"system-configuration",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
@@ -1026,9 +1026,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.174"
|
||||
version = "0.2.175"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
@@ -1330,9 +1330,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
version = "1.0.97"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
checksum = "d61789d7719defeb74ea5fe81f2fdfdbd28a803847077cecce2ff14e1472f6f1"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -1358,9 +1358,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "prost"
|
||||
version = "0.13.5"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
|
||||
checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"prost-derive",
|
||||
@@ -1368,9 +1368,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "prost-derive"
|
||||
version = "0.13.5"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
|
||||
checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools",
|
||||
@@ -1381,9 +1381,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "prost-types"
|
||||
version = "0.13.5-serde3"
|
||||
version = "0.14.1-serde2"
|
||||
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
|
||||
checksum = "e42128b6e3a6655aa5f72ac65a33848a512eb9b23e98986adc4bbe6559ea88ce"
|
||||
checksum = "c6bdb43aea117477820c164442f4e943ac7690d0dbe66cde45d78e0f7bb34386"
|
||||
dependencies = [
|
||||
"prost",
|
||||
"serde",
|
||||
@@ -1403,7 +1403,7 @@ dependencies = [
|
||||
"rustc-hash",
|
||||
"rustls",
|
||||
"socket2 0.5.10",
|
||||
"thiserror 2.0.12",
|
||||
"thiserror 2.0.14",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"web-time",
|
||||
@@ -1424,7 +1424,7 @@ dependencies = [
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"slab",
|
||||
"thiserror 2.0.12",
|
||||
"thiserror 2.0.14",
|
||||
"tinyvec",
|
||||
"tracing",
|
||||
"web-time",
|
||||
@@ -1441,7 +1441,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"socket2 0.5.10",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1655,9 +1655,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.12.22"
|
||||
version = "0.12.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531"
|
||||
checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
@@ -1734,14 +1734,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rust-grpc"
|
||||
version = "1.3.4"
|
||||
version = "1.6.1"
|
||||
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
|
||||
checksum = "ffab535c98c3a298cd092126036d5f8e40b9e600d24941823fb67a788be387ee"
|
||||
checksum = "0793cf131a9c4746000533af36aadbfb34ec6877c9f1664f94c1a110df6628ce"
|
||||
dependencies = [
|
||||
"prost",
|
||||
"prost-types",
|
||||
"serde",
|
||||
"tonic",
|
||||
"tonic-prost",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1834,9 +1835,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.21"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
@@ -2008,9 +2009,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.10"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
|
||||
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
@@ -2056,7 +2057,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "submissions-api"
|
||||
version = "0.8.2"
|
||||
version = "0.9.1"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"reqwest",
|
||||
@@ -2074,9 +2075,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.104"
|
||||
version = "2.0.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
||||
checksum = "7bc3fcb250e53458e712715cf74285c1f889686520d79294a9ef3bd7aa1fc619"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2135,11 +2136,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.12"
|
||||
version = "2.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
||||
checksum = "0b0949c3a6c842cbde3f1686d6eea5a010516deb7085f79db747562d4102f41e"
|
||||
dependencies = [
|
||||
"thiserror-impl 2.0.12",
|
||||
"thiserror-impl 2.0.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2155,9 +2156,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.12"
|
||||
version = "2.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
||||
checksum = "cc5b44b4ab9c2fdd0e0512e6bece8388e214c0749f5862b114cc5b7a25daf227"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2307,9 +2308,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tonic"
|
||||
version = "0.13.1"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9"
|
||||
checksum = "67ac5a8627ada0968acec063a4746bf79588aa03ccb66db2f75d7dce26722a40"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum",
|
||||
@@ -2324,8 +2325,8 @@ dependencies = [
|
||||
"hyper-util",
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
"prost",
|
||||
"socket2 0.5.10",
|
||||
"socket2 0.6.0",
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tower",
|
||||
@@ -2334,6 +2335,17 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tonic-prost"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9c511b9a96d40cb12b7d5d00464446acf3b9105fd3ce25437cfe41c92b1c87d"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"prost",
|
||||
"tonic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.5.2"
|
||||
|
||||
@@ -64,6 +64,8 @@ services:
|
||||
- ROBLOX_GROUP_ID=17032139 # "None" is special case string value
|
||||
- API_HOST_INTERNAL=http://submissions:8083/v1
|
||||
- NATS_HOST=nats:4222
|
||||
- LOAD_ASSET_VERSION_PLACE_ID=14001440964
|
||||
- LOAD_ASSET_VERSION_UNIVERSE_ID=4850603885
|
||||
depends_on:
|
||||
- nats
|
||||
# note: this races the submissions which creates a nats stream
|
||||
|
||||
2
go.mod
2
go.mod
@@ -6,7 +6,7 @@ toolchain go1.24.5
|
||||
|
||||
require (
|
||||
git.itzana.me/StrafesNET/dev-service v0.0.0-20250628052121-92af8193b5ed
|
||||
git.itzana.me/strafesnet/go-grpc v0.0.0-20250807005013-301d35b914ef
|
||||
git.itzana.me/strafesnet/go-grpc v0.0.0-20250814235656-6a41b31a1a33
|
||||
git.itzana.me/strafesnet/utils v0.0.0-20220716194944-d8ca164052f9
|
||||
github.com/dchest/siphash v1.2.3
|
||||
github.com/gin-gonic/gin v1.10.1
|
||||
|
||||
4
go.sum
4
go.sum
@@ -2,8 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
git.itzana.me/StrafesNET/dev-service v0.0.0-20250628052121-92af8193b5ed h1:eGWIQx2AOrSsLC2dieuSs8MCliRE60tvpZnmxsTBtKc=
|
||||
git.itzana.me/StrafesNET/dev-service v0.0.0-20250628052121-92af8193b5ed/go.mod h1:KJal0K++M6HEzSry6JJ2iDPZtOQn5zSstNlDbU3X4Jg=
|
||||
git.itzana.me/strafesnet/go-grpc v0.0.0-20250807005013-301d35b914ef h1:SJi4V4+xzScFnbMRN1gkZxcqR1xKfiT7CaXanLltEzw=
|
||||
git.itzana.me/strafesnet/go-grpc v0.0.0-20250807005013-301d35b914ef/go.mod h1:X7XTRUScRkBWq8q8bplbeso105RPDlnY7J6Wy1IwBMs=
|
||||
git.itzana.me/strafesnet/go-grpc v0.0.0-20250814235656-6a41b31a1a33 h1:7dzfLFXcrNHRSrS1CxTDC9yQLIfbcsQHLFIPeTyMFbE=
|
||||
git.itzana.me/strafesnet/go-grpc v0.0.0-20250814235656-6a41b31a1a33/go.mod h1:X7XTRUScRkBWq8q8bplbeso105RPDlnY7J6Wy1IwBMs=
|
||||
git.itzana.me/strafesnet/utils v0.0.0-20220716194944-d8ca164052f9 h1:7lU6jyR7S7Rhh1dnUp7GyIRHUTBXZagw8F4n4hOyxLw=
|
||||
git.itzana.me/strafesnet/utils v0.0.0-20220716194944-d8ca164052f9/go.mod h1:uyYerSieEt4v0MJCdPLppG0LtJ4Yj035vuTetWGsxjY=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
|
||||
81
openapi.yaml
81
openapi.yaml
@@ -244,6 +244,12 @@ paths:
|
||||
type: integer
|
||||
format: int64
|
||||
minimum: 0
|
||||
- name: AssetVersion
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
minimum: 0
|
||||
- name: TargetAssetID
|
||||
in: query
|
||||
schema:
|
||||
@@ -312,6 +318,21 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/mapfixes/migrate:
|
||||
post:
|
||||
summary: Perform the Uploaded -> Released migration.
|
||||
operationId: migrateMapfixes
|
||||
tags:
|
||||
- Mapfixes
|
||||
responses:
|
||||
"204":
|
||||
description: Successful response
|
||||
default:
|
||||
description: General Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/mapfixes/{MapfixID}:
|
||||
get:
|
||||
summary: Retrieve map with ID
|
||||
@@ -587,7 +608,7 @@ paths:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/mapfixes/{MapfixID}/status/trigger-upload:
|
||||
post:
|
||||
summary: Role Admin changes status from Validated -> Uploading
|
||||
summary: Role MapfixUpload changes status from Validated -> Uploading
|
||||
operationId: actionMapfixTriggerUpload
|
||||
tags:
|
||||
- Mapfixes
|
||||
@@ -604,7 +625,7 @@ paths:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/mapfixes/{MapfixID}/status/reset-uploading:
|
||||
post:
|
||||
summary: Role Admin manually resets uploading softlock and changes status from Uploading -> Validated
|
||||
summary: Role MapfixUpload manually resets uploading softlock and changes status from Uploading -> Validated
|
||||
operationId: actionMapfixValidated
|
||||
tags:
|
||||
- Mapfixes
|
||||
@@ -619,6 +640,40 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/mapfixes/{MapfixID}/status/trigger-release:
|
||||
post:
|
||||
summary: Role MapfixUpload changes status from Uploaded -> Releasing
|
||||
operationId: actionMapfixTriggerRelease
|
||||
tags:
|
||||
- Mapfixes
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/MapfixID'
|
||||
responses:
|
||||
"204":
|
||||
description: Successful response
|
||||
default:
|
||||
description: General Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/mapfixes/{MapfixID}/status/reset-releasing:
|
||||
post:
|
||||
summary: Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded
|
||||
operationId: actionMapfixUploaded
|
||||
tags:
|
||||
- Mapfixes
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/MapfixID'
|
||||
responses:
|
||||
"204":
|
||||
description: Successful response
|
||||
default:
|
||||
description: General Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/operations/{OperationID}:
|
||||
get:
|
||||
summary: Retrieve operation with ID
|
||||
@@ -698,6 +753,12 @@ paths:
|
||||
type: integer
|
||||
format: int64
|
||||
minimum: 0
|
||||
- name: AssetVersion
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
minimum: 0
|
||||
- name: UploadedAssetID
|
||||
in: query
|
||||
schema:
|
||||
@@ -1067,7 +1128,7 @@ paths:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/submissions/{SubmissionID}/status/trigger-upload:
|
||||
post:
|
||||
summary: Role Admin changes status from Validated -> Uploading
|
||||
summary: Role SubmissionUpload changes status from Validated -> Uploading
|
||||
operationId: actionSubmissionTriggerUpload
|
||||
tags:
|
||||
- Submissions
|
||||
@@ -1084,7 +1145,7 @@ paths:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/submissions/{SubmissionID}/status/reset-uploading:
|
||||
post:
|
||||
summary: Role Admin manually resets uploading softlock and changes status from Uploading -> Validated
|
||||
summary: Role SubmissionUpload manually resets uploading softlock and changes status from Uploading -> Validated
|
||||
operationId: actionSubmissionValidated
|
||||
tags:
|
||||
- Submissions
|
||||
@@ -1101,7 +1162,7 @@ paths:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/release-submissions:
|
||||
post:
|
||||
summary: Release a set of uploaded maps
|
||||
summary: Release a set of uploaded maps. Role SubmissionRelease
|
||||
operationId: releaseSubmissions
|
||||
tags:
|
||||
- Submissions
|
||||
@@ -1624,6 +1685,8 @@ components:
|
||||
- Submitter
|
||||
- AssetID
|
||||
- AssetVersion
|
||||
# - ValidatedAssetID
|
||||
# - ValidatedAssetVersion
|
||||
- Completed
|
||||
- TargetAssetID
|
||||
- StatusID
|
||||
@@ -1664,6 +1727,14 @@ components:
|
||||
type: integer
|
||||
format: int64
|
||||
minimum: 0
|
||||
ValidatedAssetID:
|
||||
type: integer
|
||||
format: int64
|
||||
minimum: 0
|
||||
ValidatedAssetVersion:
|
||||
type: integer
|
||||
format: int64
|
||||
minimum: 0
|
||||
Completed:
|
||||
type: boolean
|
||||
TargetAssetID:
|
||||
|
||||
@@ -66,6 +66,12 @@ type Invoker interface {
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/revoke
|
||||
ActionMapfixRevoke(ctx context.Context, params ActionMapfixRevokeParams) error
|
||||
// ActionMapfixTriggerRelease invokes actionMapfixTriggerRelease operation.
|
||||
//
|
||||
// Role MapfixUpload changes status from Uploaded -> Releasing.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-release
|
||||
ActionMapfixTriggerRelease(ctx context.Context, params ActionMapfixTriggerReleaseParams) error
|
||||
// ActionMapfixTriggerSubmit invokes actionMapfixTriggerSubmit operation.
|
||||
//
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||
@@ -80,7 +86,7 @@ type Invoker interface {
|
||||
ActionMapfixTriggerSubmitUnchecked(ctx context.Context, params ActionMapfixTriggerSubmitUncheckedParams) error
|
||||
// ActionMapfixTriggerUpload invokes actionMapfixTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
// Role MapfixUpload changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-upload
|
||||
ActionMapfixTriggerUpload(ctx context.Context, params ActionMapfixTriggerUploadParams) error
|
||||
@@ -90,9 +96,15 @@ type Invoker interface {
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-validate
|
||||
ActionMapfixTriggerValidate(ctx context.Context, params ActionMapfixTriggerValidateParams) error
|
||||
// ActionMapfixUploaded invokes actionMapfixUploaded operation.
|
||||
//
|
||||
// Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-releasing
|
||||
ActionMapfixUploaded(ctx context.Context, params ActionMapfixUploadedParams) error
|
||||
// ActionMapfixValidated invokes actionMapfixValidated operation.
|
||||
//
|
||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
// Role MapfixUpload manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-uploading
|
||||
ActionMapfixValidated(ctx context.Context, params ActionMapfixValidatedParams) error
|
||||
@@ -147,7 +159,7 @@ type Invoker interface {
|
||||
ActionSubmissionTriggerSubmitUnchecked(ctx context.Context, params ActionSubmissionTriggerSubmitUncheckedParams) error
|
||||
// ActionSubmissionTriggerUpload invokes actionSubmissionTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
// Role SubmissionUpload changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/trigger-upload
|
||||
ActionSubmissionTriggerUpload(ctx context.Context, params ActionSubmissionTriggerUploadParams) error
|
||||
@@ -159,7 +171,8 @@ type Invoker interface {
|
||||
ActionSubmissionTriggerValidate(ctx context.Context, params ActionSubmissionTriggerValidateParams) error
|
||||
// ActionSubmissionValidated invokes actionSubmissionValidated operation.
|
||||
//
|
||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
// Role SubmissionUpload manually resets uploading softlock and changes status from Uploading ->
|
||||
// Validated.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/reset-uploading
|
||||
ActionSubmissionValidated(ctx context.Context, params ActionSubmissionValidatedParams) error
|
||||
@@ -301,9 +314,15 @@ type Invoker interface {
|
||||
//
|
||||
// GET /submissions
|
||||
ListSubmissions(ctx context.Context, params ListSubmissionsParams) (*Submissions, error)
|
||||
// MigrateMapfixes invokes migrateMapfixes operation.
|
||||
//
|
||||
// Perform the Uploaded -> Released migration.
|
||||
//
|
||||
// POST /mapfixes/migrate
|
||||
MigrateMapfixes(ctx context.Context) error
|
||||
// ReleaseSubmissions invokes releaseSubmissions operation.
|
||||
//
|
||||
// Release a set of uploaded maps.
|
||||
// Release a set of uploaded maps. Role SubmissionRelease.
|
||||
//
|
||||
// POST /release-submissions
|
||||
ReleaseSubmissions(ctx context.Context, request []ReleaseInfo) error
|
||||
@@ -1157,6 +1176,130 @@ func (c *Client) sendActionMapfixRevoke(ctx context.Context, params ActionMapfix
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerRelease invokes actionMapfixTriggerRelease operation.
|
||||
//
|
||||
// Role MapfixUpload changes status from Uploaded -> Releasing.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-release
|
||||
func (c *Client) ActionMapfixTriggerRelease(ctx context.Context, params ActionMapfixTriggerReleaseParams) error {
|
||||
_, err := c.sendActionMapfixTriggerRelease(ctx, params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) sendActionMapfixTriggerRelease(ctx context.Context, params ActionMapfixTriggerReleaseParams) (res *ActionMapfixTriggerReleaseNoContent, err error) {
|
||||
otelAttrs := []attribute.KeyValue{
|
||||
otelogen.OperationID("actionMapfixTriggerRelease"),
|
||||
semconv.HTTPRequestMethodKey.String("POST"),
|
||||
semconv.HTTPRouteKey.String("/mapfixes/{MapfixID}/status/trigger-release"),
|
||||
}
|
||||
|
||||
// Run stopwatch.
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||
elapsedDuration := time.Since(startTime)
|
||||
c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...))
|
||||
}()
|
||||
|
||||
// Increment request counter.
|
||||
c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
|
||||
|
||||
// Start a span for this request.
|
||||
ctx, span := c.cfg.Tracer.Start(ctx, ActionMapfixTriggerReleaseOperation,
|
||||
trace.WithAttributes(otelAttrs...),
|
||||
clientSpanKind,
|
||||
)
|
||||
// Track stage for error reporting.
|
||||
var stage string
|
||||
defer func() {
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, stage)
|
||||
c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
|
||||
}
|
||||
span.End()
|
||||
}()
|
||||
|
||||
stage = "BuildURL"
|
||||
u := uri.Clone(c.requestURL(ctx))
|
||||
var pathParts [3]string
|
||||
pathParts[0] = "/mapfixes/"
|
||||
{
|
||||
// Encode "MapfixID" parameter.
|
||||
e := uri.NewPathEncoder(uri.PathEncoderConfig{
|
||||
Param: "MapfixID",
|
||||
Style: uri.PathStyleSimple,
|
||||
Explode: false,
|
||||
})
|
||||
if err := func() error {
|
||||
return e.EncodeValue(conv.Int64ToString(params.MapfixID))
|
||||
}(); err != nil {
|
||||
return res, errors.Wrap(err, "encode path")
|
||||
}
|
||||
encoded, err := e.Result()
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "encode path")
|
||||
}
|
||||
pathParts[1] = encoded
|
||||
}
|
||||
pathParts[2] = "/status/trigger-release"
|
||||
uri.AddPathParts(u, pathParts[:]...)
|
||||
|
||||
stage = "EncodeRequest"
|
||||
r, err := ht.NewRequest(ctx, "POST", u)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "create request")
|
||||
}
|
||||
|
||||
{
|
||||
type bitset = [1]uint8
|
||||
var satisfied bitset
|
||||
{
|
||||
stage = "Security:CookieAuth"
|
||||
switch err := c.securityCookieAuth(ctx, ActionMapfixTriggerReleaseOperation, r); {
|
||||
case err == nil: // if NO error
|
||||
satisfied[0] |= 1 << 0
|
||||
case errors.Is(err, ogenerrors.ErrSkipClientSecurity):
|
||||
// Skip this security.
|
||||
default:
|
||||
return res, errors.Wrap(err, "security \"CookieAuth\"")
|
||||
}
|
||||
}
|
||||
|
||||
if ok := func() bool {
|
||||
nextRequirement:
|
||||
for _, requirement := range []bitset{
|
||||
{0b00000001},
|
||||
} {
|
||||
for i, mask := range requirement {
|
||||
if satisfied[i]&mask != mask {
|
||||
continue nextRequirement
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}(); !ok {
|
||||
return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied
|
||||
}
|
||||
}
|
||||
|
||||
stage = "SendRequest"
|
||||
resp, err := c.cfg.Client.Do(r)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "do request")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
stage = "DecodeResponse"
|
||||
result, err := decodeActionMapfixTriggerReleaseResponse(resp)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "decode response")
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerSubmit invokes actionMapfixTriggerSubmit operation.
|
||||
//
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||
@@ -1407,7 +1550,7 @@ func (c *Client) sendActionMapfixTriggerSubmitUnchecked(ctx context.Context, par
|
||||
|
||||
// ActionMapfixTriggerUpload invokes actionMapfixTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
// Role MapfixUpload changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-upload
|
||||
func (c *Client) ActionMapfixTriggerUpload(ctx context.Context, params ActionMapfixTriggerUploadParams) error {
|
||||
@@ -1653,9 +1796,133 @@ func (c *Client) sendActionMapfixTriggerValidate(ctx context.Context, params Act
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ActionMapfixUploaded invokes actionMapfixUploaded operation.
|
||||
//
|
||||
// Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-releasing
|
||||
func (c *Client) ActionMapfixUploaded(ctx context.Context, params ActionMapfixUploadedParams) error {
|
||||
_, err := c.sendActionMapfixUploaded(ctx, params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) sendActionMapfixUploaded(ctx context.Context, params ActionMapfixUploadedParams) (res *ActionMapfixUploadedNoContent, err error) {
|
||||
otelAttrs := []attribute.KeyValue{
|
||||
otelogen.OperationID("actionMapfixUploaded"),
|
||||
semconv.HTTPRequestMethodKey.String("POST"),
|
||||
semconv.HTTPRouteKey.String("/mapfixes/{MapfixID}/status/reset-releasing"),
|
||||
}
|
||||
|
||||
// Run stopwatch.
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||
elapsedDuration := time.Since(startTime)
|
||||
c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...))
|
||||
}()
|
||||
|
||||
// Increment request counter.
|
||||
c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
|
||||
|
||||
// Start a span for this request.
|
||||
ctx, span := c.cfg.Tracer.Start(ctx, ActionMapfixUploadedOperation,
|
||||
trace.WithAttributes(otelAttrs...),
|
||||
clientSpanKind,
|
||||
)
|
||||
// Track stage for error reporting.
|
||||
var stage string
|
||||
defer func() {
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, stage)
|
||||
c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
|
||||
}
|
||||
span.End()
|
||||
}()
|
||||
|
||||
stage = "BuildURL"
|
||||
u := uri.Clone(c.requestURL(ctx))
|
||||
var pathParts [3]string
|
||||
pathParts[0] = "/mapfixes/"
|
||||
{
|
||||
// Encode "MapfixID" parameter.
|
||||
e := uri.NewPathEncoder(uri.PathEncoderConfig{
|
||||
Param: "MapfixID",
|
||||
Style: uri.PathStyleSimple,
|
||||
Explode: false,
|
||||
})
|
||||
if err := func() error {
|
||||
return e.EncodeValue(conv.Int64ToString(params.MapfixID))
|
||||
}(); err != nil {
|
||||
return res, errors.Wrap(err, "encode path")
|
||||
}
|
||||
encoded, err := e.Result()
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "encode path")
|
||||
}
|
||||
pathParts[1] = encoded
|
||||
}
|
||||
pathParts[2] = "/status/reset-releasing"
|
||||
uri.AddPathParts(u, pathParts[:]...)
|
||||
|
||||
stage = "EncodeRequest"
|
||||
r, err := ht.NewRequest(ctx, "POST", u)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "create request")
|
||||
}
|
||||
|
||||
{
|
||||
type bitset = [1]uint8
|
||||
var satisfied bitset
|
||||
{
|
||||
stage = "Security:CookieAuth"
|
||||
switch err := c.securityCookieAuth(ctx, ActionMapfixUploadedOperation, r); {
|
||||
case err == nil: // if NO error
|
||||
satisfied[0] |= 1 << 0
|
||||
case errors.Is(err, ogenerrors.ErrSkipClientSecurity):
|
||||
// Skip this security.
|
||||
default:
|
||||
return res, errors.Wrap(err, "security \"CookieAuth\"")
|
||||
}
|
||||
}
|
||||
|
||||
if ok := func() bool {
|
||||
nextRequirement:
|
||||
for _, requirement := range []bitset{
|
||||
{0b00000001},
|
||||
} {
|
||||
for i, mask := range requirement {
|
||||
if satisfied[i]&mask != mask {
|
||||
continue nextRequirement
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}(); !ok {
|
||||
return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied
|
||||
}
|
||||
}
|
||||
|
||||
stage = "SendRequest"
|
||||
resp, err := c.cfg.Client.Do(r)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "do request")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
stage = "DecodeResponse"
|
||||
result, err := decodeActionMapfixUploadedResponse(resp)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "decode response")
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ActionMapfixValidated invokes actionMapfixValidated operation.
|
||||
//
|
||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
// Role MapfixUpload manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-uploading
|
||||
func (c *Client) ActionMapfixValidated(ctx context.Context, params ActionMapfixValidatedParams) error {
|
||||
@@ -2772,7 +3039,7 @@ func (c *Client) sendActionSubmissionTriggerSubmitUnchecked(ctx context.Context,
|
||||
|
||||
// ActionSubmissionTriggerUpload invokes actionSubmissionTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
// Role SubmissionUpload changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/trigger-upload
|
||||
func (c *Client) ActionSubmissionTriggerUpload(ctx context.Context, params ActionSubmissionTriggerUploadParams) error {
|
||||
@@ -3020,7 +3287,8 @@ func (c *Client) sendActionSubmissionTriggerValidate(ctx context.Context, params
|
||||
|
||||
// ActionSubmissionValidated invokes actionSubmissionValidated operation.
|
||||
//
|
||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
// Role SubmissionUpload manually resets uploading softlock and changes status from Uploading ->
|
||||
// Validated.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/reset-uploading
|
||||
func (c *Client) ActionSubmissionValidated(ctx context.Context, params ActionSubmissionValidatedParams) error {
|
||||
@@ -5184,6 +5452,23 @@ func (c *Client) sendListMapfixes(ctx context.Context, params ListMapfixesParams
|
||||
return res, errors.Wrap(err, "encode query")
|
||||
}
|
||||
}
|
||||
{
|
||||
// Encode "AssetVersion" parameter.
|
||||
cfg := uri.QueryParameterEncodingConfig{
|
||||
Name: "AssetVersion",
|
||||
Style: uri.QueryStyleForm,
|
||||
Explode: true,
|
||||
}
|
||||
|
||||
if err := q.EncodeParam(cfg, func(e uri.Encoder) error {
|
||||
if val, ok := params.AssetVersion.Get(); ok {
|
||||
return e.EncodeValue(conv.Int64ToString(val))
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return res, errors.Wrap(err, "encode query")
|
||||
}
|
||||
}
|
||||
{
|
||||
// Encode "TargetAssetID" parameter.
|
||||
cfg := uri.QueryParameterEncodingConfig{
|
||||
@@ -6063,6 +6348,23 @@ func (c *Client) sendListSubmissions(ctx context.Context, params ListSubmissions
|
||||
return res, errors.Wrap(err, "encode query")
|
||||
}
|
||||
}
|
||||
{
|
||||
// Encode "AssetVersion" parameter.
|
||||
cfg := uri.QueryParameterEncodingConfig{
|
||||
Name: "AssetVersion",
|
||||
Style: uri.QueryStyleForm,
|
||||
Explode: true,
|
||||
}
|
||||
|
||||
if err := q.EncodeParam(cfg, func(e uri.Encoder) error {
|
||||
if val, ok := params.AssetVersion.Get(); ok {
|
||||
return e.EncodeValue(conv.Int64ToString(val))
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return res, errors.Wrap(err, "encode query")
|
||||
}
|
||||
}
|
||||
{
|
||||
// Encode "UploadedAssetID" parameter.
|
||||
cfg := uri.QueryParameterEncodingConfig{
|
||||
@@ -6121,9 +6423,114 @@ func (c *Client) sendListSubmissions(ctx context.Context, params ListSubmissions
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// MigrateMapfixes invokes migrateMapfixes operation.
|
||||
//
|
||||
// Perform the Uploaded -> Released migration.
|
||||
//
|
||||
// POST /mapfixes/migrate
|
||||
func (c *Client) MigrateMapfixes(ctx context.Context) error {
|
||||
_, err := c.sendMigrateMapfixes(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) sendMigrateMapfixes(ctx context.Context) (res *MigrateMapfixesNoContent, err error) {
|
||||
otelAttrs := []attribute.KeyValue{
|
||||
otelogen.OperationID("migrateMapfixes"),
|
||||
semconv.HTTPRequestMethodKey.String("POST"),
|
||||
semconv.HTTPRouteKey.String("/mapfixes/migrate"),
|
||||
}
|
||||
|
||||
// Run stopwatch.
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||
elapsedDuration := time.Since(startTime)
|
||||
c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...))
|
||||
}()
|
||||
|
||||
// Increment request counter.
|
||||
c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
|
||||
|
||||
// Start a span for this request.
|
||||
ctx, span := c.cfg.Tracer.Start(ctx, MigrateMapfixesOperation,
|
||||
trace.WithAttributes(otelAttrs...),
|
||||
clientSpanKind,
|
||||
)
|
||||
// Track stage for error reporting.
|
||||
var stage string
|
||||
defer func() {
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, stage)
|
||||
c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
|
||||
}
|
||||
span.End()
|
||||
}()
|
||||
|
||||
stage = "BuildURL"
|
||||
u := uri.Clone(c.requestURL(ctx))
|
||||
var pathParts [1]string
|
||||
pathParts[0] = "/mapfixes/migrate"
|
||||
uri.AddPathParts(u, pathParts[:]...)
|
||||
|
||||
stage = "EncodeRequest"
|
||||
r, err := ht.NewRequest(ctx, "POST", u)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "create request")
|
||||
}
|
||||
|
||||
{
|
||||
type bitset = [1]uint8
|
||||
var satisfied bitset
|
||||
{
|
||||
stage = "Security:CookieAuth"
|
||||
switch err := c.securityCookieAuth(ctx, MigrateMapfixesOperation, r); {
|
||||
case err == nil: // if NO error
|
||||
satisfied[0] |= 1 << 0
|
||||
case errors.Is(err, ogenerrors.ErrSkipClientSecurity):
|
||||
// Skip this security.
|
||||
default:
|
||||
return res, errors.Wrap(err, "security \"CookieAuth\"")
|
||||
}
|
||||
}
|
||||
|
||||
if ok := func() bool {
|
||||
nextRequirement:
|
||||
for _, requirement := range []bitset{
|
||||
{0b00000001},
|
||||
} {
|
||||
for i, mask := range requirement {
|
||||
if satisfied[i]&mask != mask {
|
||||
continue nextRequirement
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}(); !ok {
|
||||
return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied
|
||||
}
|
||||
}
|
||||
|
||||
stage = "SendRequest"
|
||||
resp, err := c.cfg.Client.Do(r)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "do request")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
stage = "DecodeResponse"
|
||||
result, err := decodeMigrateMapfixesResponse(resp)
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "decode response")
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ReleaseSubmissions invokes releaseSubmissions operation.
|
||||
//
|
||||
// Release a set of uploaded maps.
|
||||
// Release a set of uploaded maps. Role SubmissionRelease.
|
||||
//
|
||||
// POST /release-submissions
|
||||
func (c *Client) ReleaseSubmissions(ctx context.Context, request []ReleaseInfo) error {
|
||||
|
||||
@@ -1201,6 +1201,201 @@ func (s *Server) handleActionMapfixRevokeRequest(args [1]string, argsEscaped boo
|
||||
}
|
||||
}
|
||||
|
||||
// handleActionMapfixTriggerReleaseRequest handles actionMapfixTriggerRelease operation.
|
||||
//
|
||||
// Role MapfixUpload changes status from Uploaded -> Releasing.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-release
|
||||
func (s *Server) handleActionMapfixTriggerReleaseRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
||||
statusWriter := &codeRecorder{ResponseWriter: w}
|
||||
w = statusWriter
|
||||
otelAttrs := []attribute.KeyValue{
|
||||
otelogen.OperationID("actionMapfixTriggerRelease"),
|
||||
semconv.HTTPRequestMethodKey.String("POST"),
|
||||
semconv.HTTPRouteKey.String("/mapfixes/{MapfixID}/status/trigger-release"),
|
||||
}
|
||||
|
||||
// Start a span for this request.
|
||||
ctx, span := s.cfg.Tracer.Start(r.Context(), ActionMapfixTriggerReleaseOperation,
|
||||
trace.WithAttributes(otelAttrs...),
|
||||
serverSpanKind,
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
// Add Labeler to context.
|
||||
labeler := &Labeler{attrs: otelAttrs}
|
||||
ctx = contextWithLabeler(ctx, labeler)
|
||||
|
||||
// Run stopwatch.
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
elapsedDuration := time.Since(startTime)
|
||||
|
||||
attrSet := labeler.AttributeSet()
|
||||
attrs := attrSet.ToSlice()
|
||||
code := statusWriter.status
|
||||
if code != 0 {
|
||||
codeAttr := semconv.HTTPResponseStatusCode(code)
|
||||
attrs = append(attrs, codeAttr)
|
||||
span.SetAttributes(codeAttr)
|
||||
}
|
||||
attrOpt := metric.WithAttributes(attrs...)
|
||||
|
||||
// Increment request counter.
|
||||
s.requests.Add(ctx, 1, attrOpt)
|
||||
|
||||
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
|
||||
}()
|
||||
|
||||
var (
|
||||
recordError = func(stage string, err error) {
|
||||
span.RecordError(err)
|
||||
|
||||
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
|
||||
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
|
||||
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
|
||||
// max redirects exceeded), in which case status MUST be set to Error.
|
||||
code := statusWriter.status
|
||||
if code >= 100 && code < 500 {
|
||||
span.SetStatus(codes.Error, stage)
|
||||
}
|
||||
|
||||
attrSet := labeler.AttributeSet()
|
||||
attrs := attrSet.ToSlice()
|
||||
if code != 0 {
|
||||
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
|
||||
}
|
||||
|
||||
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
|
||||
}
|
||||
err error
|
||||
opErrContext = ogenerrors.OperationContext{
|
||||
Name: ActionMapfixTriggerReleaseOperation,
|
||||
ID: "actionMapfixTriggerRelease",
|
||||
}
|
||||
)
|
||||
{
|
||||
type bitset = [1]uint8
|
||||
var satisfied bitset
|
||||
{
|
||||
sctx, ok, err := s.securityCookieAuth(ctx, ActionMapfixTriggerReleaseOperation, r)
|
||||
if err != nil {
|
||||
err = &ogenerrors.SecurityError{
|
||||
OperationContext: opErrContext,
|
||||
Security: "CookieAuth",
|
||||
Err: err,
|
||||
}
|
||||
if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil {
|
||||
defer recordError("Security:CookieAuth", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if ok {
|
||||
satisfied[0] |= 1 << 0
|
||||
ctx = sctx
|
||||
}
|
||||
}
|
||||
|
||||
if ok := func() bool {
|
||||
nextRequirement:
|
||||
for _, requirement := range []bitset{
|
||||
{0b00000001},
|
||||
} {
|
||||
for i, mask := range requirement {
|
||||
if satisfied[i]&mask != mask {
|
||||
continue nextRequirement
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}(); !ok {
|
||||
err = &ogenerrors.SecurityError{
|
||||
OperationContext: opErrContext,
|
||||
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
|
||||
}
|
||||
if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil {
|
||||
defer recordError("Security", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
params, err := decodeActionMapfixTriggerReleaseParams(args, argsEscaped, r)
|
||||
if err != nil {
|
||||
err = &ogenerrors.DecodeParamsError{
|
||||
OperationContext: opErrContext,
|
||||
Err: err,
|
||||
}
|
||||
defer recordError("DecodeParams", err)
|
||||
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
var response *ActionMapfixTriggerReleaseNoContent
|
||||
if m := s.cfg.Middleware; m != nil {
|
||||
mreq := middleware.Request{
|
||||
Context: ctx,
|
||||
OperationName: ActionMapfixTriggerReleaseOperation,
|
||||
OperationSummary: "Role MapfixUpload changes status from Uploaded -> Releasing",
|
||||
OperationID: "actionMapfixTriggerRelease",
|
||||
Body: nil,
|
||||
Params: middleware.Parameters{
|
||||
{
|
||||
Name: "MapfixID",
|
||||
In: "path",
|
||||
}: params.MapfixID,
|
||||
},
|
||||
Raw: r,
|
||||
}
|
||||
|
||||
type (
|
||||
Request = struct{}
|
||||
Params = ActionMapfixTriggerReleaseParams
|
||||
Response = *ActionMapfixTriggerReleaseNoContent
|
||||
)
|
||||
response, err = middleware.HookMiddleware[
|
||||
Request,
|
||||
Params,
|
||||
Response,
|
||||
](
|
||||
m,
|
||||
mreq,
|
||||
unpackActionMapfixTriggerReleaseParams,
|
||||
func(ctx context.Context, request Request, params Params) (response Response, err error) {
|
||||
err = s.h.ActionMapfixTriggerRelease(ctx, params)
|
||||
return response, err
|
||||
},
|
||||
)
|
||||
} else {
|
||||
err = s.h.ActionMapfixTriggerRelease(ctx, params)
|
||||
}
|
||||
if err != nil {
|
||||
if errRes, ok := errors.Into[*ErrorStatusCode](err); ok {
|
||||
if err := encodeErrorResponse(errRes, w, span); err != nil {
|
||||
defer recordError("Internal", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if errors.Is(err, ht.ErrNotImplemented) {
|
||||
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||
return
|
||||
}
|
||||
if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil {
|
||||
defer recordError("Internal", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := encodeActionMapfixTriggerReleaseResponse(response, w, span); err != nil {
|
||||
defer recordError("EncodeResponse", err)
|
||||
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
|
||||
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// handleActionMapfixTriggerSubmitRequest handles actionMapfixTriggerSubmit operation.
|
||||
//
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||
@@ -1593,7 +1788,7 @@ func (s *Server) handleActionMapfixTriggerSubmitUncheckedRequest(args [1]string,
|
||||
|
||||
// handleActionMapfixTriggerUploadRequest handles actionMapfixTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
// Role MapfixUpload changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-upload
|
||||
func (s *Server) handleActionMapfixTriggerUploadRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
||||
@@ -1727,7 +1922,7 @@ func (s *Server) handleActionMapfixTriggerUploadRequest(args [1]string, argsEsca
|
||||
mreq := middleware.Request{
|
||||
Context: ctx,
|
||||
OperationName: ActionMapfixTriggerUploadOperation,
|
||||
OperationSummary: "Role Admin changes status from Validated -> Uploading",
|
||||
OperationSummary: "Role MapfixUpload changes status from Validated -> Uploading",
|
||||
OperationID: "actionMapfixTriggerUpload",
|
||||
Body: nil,
|
||||
Params: middleware.Parameters{
|
||||
@@ -1981,9 +2176,204 @@ func (s *Server) handleActionMapfixTriggerValidateRequest(args [1]string, argsEs
|
||||
}
|
||||
}
|
||||
|
||||
// handleActionMapfixUploadedRequest handles actionMapfixUploaded operation.
|
||||
//
|
||||
// Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-releasing
|
||||
func (s *Server) handleActionMapfixUploadedRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
||||
statusWriter := &codeRecorder{ResponseWriter: w}
|
||||
w = statusWriter
|
||||
otelAttrs := []attribute.KeyValue{
|
||||
otelogen.OperationID("actionMapfixUploaded"),
|
||||
semconv.HTTPRequestMethodKey.String("POST"),
|
||||
semconv.HTTPRouteKey.String("/mapfixes/{MapfixID}/status/reset-releasing"),
|
||||
}
|
||||
|
||||
// Start a span for this request.
|
||||
ctx, span := s.cfg.Tracer.Start(r.Context(), ActionMapfixUploadedOperation,
|
||||
trace.WithAttributes(otelAttrs...),
|
||||
serverSpanKind,
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
// Add Labeler to context.
|
||||
labeler := &Labeler{attrs: otelAttrs}
|
||||
ctx = contextWithLabeler(ctx, labeler)
|
||||
|
||||
// Run stopwatch.
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
elapsedDuration := time.Since(startTime)
|
||||
|
||||
attrSet := labeler.AttributeSet()
|
||||
attrs := attrSet.ToSlice()
|
||||
code := statusWriter.status
|
||||
if code != 0 {
|
||||
codeAttr := semconv.HTTPResponseStatusCode(code)
|
||||
attrs = append(attrs, codeAttr)
|
||||
span.SetAttributes(codeAttr)
|
||||
}
|
||||
attrOpt := metric.WithAttributes(attrs...)
|
||||
|
||||
// Increment request counter.
|
||||
s.requests.Add(ctx, 1, attrOpt)
|
||||
|
||||
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
|
||||
}()
|
||||
|
||||
var (
|
||||
recordError = func(stage string, err error) {
|
||||
span.RecordError(err)
|
||||
|
||||
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
|
||||
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
|
||||
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
|
||||
// max redirects exceeded), in which case status MUST be set to Error.
|
||||
code := statusWriter.status
|
||||
if code >= 100 && code < 500 {
|
||||
span.SetStatus(codes.Error, stage)
|
||||
}
|
||||
|
||||
attrSet := labeler.AttributeSet()
|
||||
attrs := attrSet.ToSlice()
|
||||
if code != 0 {
|
||||
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
|
||||
}
|
||||
|
||||
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
|
||||
}
|
||||
err error
|
||||
opErrContext = ogenerrors.OperationContext{
|
||||
Name: ActionMapfixUploadedOperation,
|
||||
ID: "actionMapfixUploaded",
|
||||
}
|
||||
)
|
||||
{
|
||||
type bitset = [1]uint8
|
||||
var satisfied bitset
|
||||
{
|
||||
sctx, ok, err := s.securityCookieAuth(ctx, ActionMapfixUploadedOperation, r)
|
||||
if err != nil {
|
||||
err = &ogenerrors.SecurityError{
|
||||
OperationContext: opErrContext,
|
||||
Security: "CookieAuth",
|
||||
Err: err,
|
||||
}
|
||||
if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil {
|
||||
defer recordError("Security:CookieAuth", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if ok {
|
||||
satisfied[0] |= 1 << 0
|
||||
ctx = sctx
|
||||
}
|
||||
}
|
||||
|
||||
if ok := func() bool {
|
||||
nextRequirement:
|
||||
for _, requirement := range []bitset{
|
||||
{0b00000001},
|
||||
} {
|
||||
for i, mask := range requirement {
|
||||
if satisfied[i]&mask != mask {
|
||||
continue nextRequirement
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}(); !ok {
|
||||
err = &ogenerrors.SecurityError{
|
||||
OperationContext: opErrContext,
|
||||
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
|
||||
}
|
||||
if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil {
|
||||
defer recordError("Security", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
params, err := decodeActionMapfixUploadedParams(args, argsEscaped, r)
|
||||
if err != nil {
|
||||
err = &ogenerrors.DecodeParamsError{
|
||||
OperationContext: opErrContext,
|
||||
Err: err,
|
||||
}
|
||||
defer recordError("DecodeParams", err)
|
||||
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
var response *ActionMapfixUploadedNoContent
|
||||
if m := s.cfg.Middleware; m != nil {
|
||||
mreq := middleware.Request{
|
||||
Context: ctx,
|
||||
OperationName: ActionMapfixUploadedOperation,
|
||||
OperationSummary: "Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded",
|
||||
OperationID: "actionMapfixUploaded",
|
||||
Body: nil,
|
||||
Params: middleware.Parameters{
|
||||
{
|
||||
Name: "MapfixID",
|
||||
In: "path",
|
||||
}: params.MapfixID,
|
||||
},
|
||||
Raw: r,
|
||||
}
|
||||
|
||||
type (
|
||||
Request = struct{}
|
||||
Params = ActionMapfixUploadedParams
|
||||
Response = *ActionMapfixUploadedNoContent
|
||||
)
|
||||
response, err = middleware.HookMiddleware[
|
||||
Request,
|
||||
Params,
|
||||
Response,
|
||||
](
|
||||
m,
|
||||
mreq,
|
||||
unpackActionMapfixUploadedParams,
|
||||
func(ctx context.Context, request Request, params Params) (response Response, err error) {
|
||||
err = s.h.ActionMapfixUploaded(ctx, params)
|
||||
return response, err
|
||||
},
|
||||
)
|
||||
} else {
|
||||
err = s.h.ActionMapfixUploaded(ctx, params)
|
||||
}
|
||||
if err != nil {
|
||||
if errRes, ok := errors.Into[*ErrorStatusCode](err); ok {
|
||||
if err := encodeErrorResponse(errRes, w, span); err != nil {
|
||||
defer recordError("Internal", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if errors.Is(err, ht.ErrNotImplemented) {
|
||||
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||
return
|
||||
}
|
||||
if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil {
|
||||
defer recordError("Internal", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := encodeActionMapfixUploadedResponse(response, w, span); err != nil {
|
||||
defer recordError("EncodeResponse", err)
|
||||
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
|
||||
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// handleActionMapfixValidatedRequest handles actionMapfixValidated operation.
|
||||
//
|
||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
// Role MapfixUpload manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-uploading
|
||||
func (s *Server) handleActionMapfixValidatedRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
||||
@@ -2117,7 +2507,7 @@ func (s *Server) handleActionMapfixValidatedRequest(args [1]string, argsEscaped
|
||||
mreq := middleware.Request{
|
||||
Context: ctx,
|
||||
OperationName: ActionMapfixValidatedOperation,
|
||||
OperationSummary: "Role Admin manually resets uploading softlock and changes status from Uploading -> Validated",
|
||||
OperationSummary: "Role MapfixUpload manually resets uploading softlock and changes status from Uploading -> Validated",
|
||||
OperationID: "actionMapfixValidated",
|
||||
Body: nil,
|
||||
Params: middleware.Parameters{
|
||||
@@ -3739,7 +4129,7 @@ func (s *Server) handleActionSubmissionTriggerSubmitUncheckedRequest(args [1]str
|
||||
|
||||
// handleActionSubmissionTriggerUploadRequest handles actionSubmissionTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
// Role SubmissionUpload changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/trigger-upload
|
||||
func (s *Server) handleActionSubmissionTriggerUploadRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
||||
@@ -3873,7 +4263,7 @@ func (s *Server) handleActionSubmissionTriggerUploadRequest(args [1]string, args
|
||||
mreq := middleware.Request{
|
||||
Context: ctx,
|
||||
OperationName: ActionSubmissionTriggerUploadOperation,
|
||||
OperationSummary: "Role Admin changes status from Validated -> Uploading",
|
||||
OperationSummary: "Role SubmissionUpload changes status from Validated -> Uploading",
|
||||
OperationID: "actionSubmissionTriggerUpload",
|
||||
Body: nil,
|
||||
Params: middleware.Parameters{
|
||||
@@ -4129,7 +4519,8 @@ func (s *Server) handleActionSubmissionTriggerValidateRequest(args [1]string, ar
|
||||
|
||||
// handleActionSubmissionValidatedRequest handles actionSubmissionValidated operation.
|
||||
//
|
||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
// Role SubmissionUpload manually resets uploading softlock and changes status from Uploading ->
|
||||
// Validated.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/reset-uploading
|
||||
func (s *Server) handleActionSubmissionValidatedRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
||||
@@ -4263,7 +4654,7 @@ func (s *Server) handleActionSubmissionValidatedRequest(args [1]string, argsEsca
|
||||
mreq := middleware.Request{
|
||||
Context: ctx,
|
||||
OperationName: ActionSubmissionValidatedOperation,
|
||||
OperationSummary: "Role Admin manually resets uploading softlock and changes status from Uploading -> Validated",
|
||||
OperationSummary: "Role SubmissionUpload manually resets uploading softlock and changes status from Uploading -> Validated",
|
||||
OperationID: "actionSubmissionValidated",
|
||||
Body: nil,
|
||||
Params: middleware.Parameters{
|
||||
@@ -7525,6 +7916,10 @@ func (s *Server) handleListMapfixesRequest(args [0]string, argsEscaped bool, w h
|
||||
Name: "AssetID",
|
||||
In: "query",
|
||||
}: params.AssetID,
|
||||
{
|
||||
Name: "AssetVersion",
|
||||
In: "query",
|
||||
}: params.AssetVersion,
|
||||
{
|
||||
Name: "TargetAssetID",
|
||||
In: "query",
|
||||
@@ -8374,6 +8769,10 @@ func (s *Server) handleListSubmissionsRequest(args [0]string, argsEscaped bool,
|
||||
Name: "AssetID",
|
||||
In: "query",
|
||||
}: params.AssetID,
|
||||
{
|
||||
Name: "AssetVersion",
|
||||
In: "query",
|
||||
}: params.AssetVersion,
|
||||
{
|
||||
Name: "UploadedAssetID",
|
||||
In: "query",
|
||||
@@ -8433,9 +8832,189 @@ func (s *Server) handleListSubmissionsRequest(args [0]string, argsEscaped bool,
|
||||
}
|
||||
}
|
||||
|
||||
// handleMigrateMapfixesRequest handles migrateMapfixes operation.
|
||||
//
|
||||
// Perform the Uploaded -> Released migration.
|
||||
//
|
||||
// POST /mapfixes/migrate
|
||||
func (s *Server) handleMigrateMapfixesRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
||||
statusWriter := &codeRecorder{ResponseWriter: w}
|
||||
w = statusWriter
|
||||
otelAttrs := []attribute.KeyValue{
|
||||
otelogen.OperationID("migrateMapfixes"),
|
||||
semconv.HTTPRequestMethodKey.String("POST"),
|
||||
semconv.HTTPRouteKey.String("/mapfixes/migrate"),
|
||||
}
|
||||
|
||||
// Start a span for this request.
|
||||
ctx, span := s.cfg.Tracer.Start(r.Context(), MigrateMapfixesOperation,
|
||||
trace.WithAttributes(otelAttrs...),
|
||||
serverSpanKind,
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
// Add Labeler to context.
|
||||
labeler := &Labeler{attrs: otelAttrs}
|
||||
ctx = contextWithLabeler(ctx, labeler)
|
||||
|
||||
// Run stopwatch.
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
elapsedDuration := time.Since(startTime)
|
||||
|
||||
attrSet := labeler.AttributeSet()
|
||||
attrs := attrSet.ToSlice()
|
||||
code := statusWriter.status
|
||||
if code != 0 {
|
||||
codeAttr := semconv.HTTPResponseStatusCode(code)
|
||||
attrs = append(attrs, codeAttr)
|
||||
span.SetAttributes(codeAttr)
|
||||
}
|
||||
attrOpt := metric.WithAttributes(attrs...)
|
||||
|
||||
// Increment request counter.
|
||||
s.requests.Add(ctx, 1, attrOpt)
|
||||
|
||||
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
|
||||
}()
|
||||
|
||||
var (
|
||||
recordError = func(stage string, err error) {
|
||||
span.RecordError(err)
|
||||
|
||||
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
|
||||
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
|
||||
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
|
||||
// max redirects exceeded), in which case status MUST be set to Error.
|
||||
code := statusWriter.status
|
||||
if code >= 100 && code < 500 {
|
||||
span.SetStatus(codes.Error, stage)
|
||||
}
|
||||
|
||||
attrSet := labeler.AttributeSet()
|
||||
attrs := attrSet.ToSlice()
|
||||
if code != 0 {
|
||||
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
|
||||
}
|
||||
|
||||
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
|
||||
}
|
||||
err error
|
||||
opErrContext = ogenerrors.OperationContext{
|
||||
Name: MigrateMapfixesOperation,
|
||||
ID: "migrateMapfixes",
|
||||
}
|
||||
)
|
||||
{
|
||||
type bitset = [1]uint8
|
||||
var satisfied bitset
|
||||
{
|
||||
sctx, ok, err := s.securityCookieAuth(ctx, MigrateMapfixesOperation, r)
|
||||
if err != nil {
|
||||
err = &ogenerrors.SecurityError{
|
||||
OperationContext: opErrContext,
|
||||
Security: "CookieAuth",
|
||||
Err: err,
|
||||
}
|
||||
if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil {
|
||||
defer recordError("Security:CookieAuth", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if ok {
|
||||
satisfied[0] |= 1 << 0
|
||||
ctx = sctx
|
||||
}
|
||||
}
|
||||
|
||||
if ok := func() bool {
|
||||
nextRequirement:
|
||||
for _, requirement := range []bitset{
|
||||
{0b00000001},
|
||||
} {
|
||||
for i, mask := range requirement {
|
||||
if satisfied[i]&mask != mask {
|
||||
continue nextRequirement
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}(); !ok {
|
||||
err = &ogenerrors.SecurityError{
|
||||
OperationContext: opErrContext,
|
||||
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
|
||||
}
|
||||
if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil {
|
||||
defer recordError("Security", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var response *MigrateMapfixesNoContent
|
||||
if m := s.cfg.Middleware; m != nil {
|
||||
mreq := middleware.Request{
|
||||
Context: ctx,
|
||||
OperationName: MigrateMapfixesOperation,
|
||||
OperationSummary: "Perform the Uploaded -> Released migration.",
|
||||
OperationID: "migrateMapfixes",
|
||||
Body: nil,
|
||||
Params: middleware.Parameters{},
|
||||
Raw: r,
|
||||
}
|
||||
|
||||
type (
|
||||
Request = struct{}
|
||||
Params = struct{}
|
||||
Response = *MigrateMapfixesNoContent
|
||||
)
|
||||
response, err = middleware.HookMiddleware[
|
||||
Request,
|
||||
Params,
|
||||
Response,
|
||||
](
|
||||
m,
|
||||
mreq,
|
||||
nil,
|
||||
func(ctx context.Context, request Request, params Params) (response Response, err error) {
|
||||
err = s.h.MigrateMapfixes(ctx)
|
||||
return response, err
|
||||
},
|
||||
)
|
||||
} else {
|
||||
err = s.h.MigrateMapfixes(ctx)
|
||||
}
|
||||
if err != nil {
|
||||
if errRes, ok := errors.Into[*ErrorStatusCode](err); ok {
|
||||
if err := encodeErrorResponse(errRes, w, span); err != nil {
|
||||
defer recordError("Internal", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if errors.Is(err, ht.ErrNotImplemented) {
|
||||
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||
return
|
||||
}
|
||||
if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil {
|
||||
defer recordError("Internal", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := encodeMigrateMapfixesResponse(response, w, span); err != nil {
|
||||
defer recordError("EncodeResponse", err)
|
||||
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
|
||||
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// handleReleaseSubmissionsRequest handles releaseSubmissions operation.
|
||||
//
|
||||
// Release a set of uploaded maps.
|
||||
// Release a set of uploaded maps. Role SubmissionRelease.
|
||||
//
|
||||
// POST /release-submissions
|
||||
func (s *Server) handleReleaseSubmissionsRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
||||
@@ -8574,7 +9153,7 @@ func (s *Server) handleReleaseSubmissionsRequest(args [0]string, argsEscaped boo
|
||||
mreq := middleware.Request{
|
||||
Context: ctx,
|
||||
OperationName: ReleaseSubmissionsOperation,
|
||||
OperationSummary: "Release a set of uploaded maps",
|
||||
OperationSummary: "Release a set of uploaded maps. Role SubmissionRelease",
|
||||
OperationID: "releaseSubmissions",
|
||||
Body: request,
|
||||
Params: middleware.Parameters{},
|
||||
|
||||
@@ -726,6 +726,18 @@ func (s *Mapfix) encodeFields(e *jx.Encoder) {
|
||||
e.FieldStart("AssetVersion")
|
||||
e.Int64(s.AssetVersion)
|
||||
}
|
||||
{
|
||||
if s.ValidatedAssetID.Set {
|
||||
e.FieldStart("ValidatedAssetID")
|
||||
s.ValidatedAssetID.Encode(e)
|
||||
}
|
||||
}
|
||||
{
|
||||
if s.ValidatedAssetVersion.Set {
|
||||
e.FieldStart("ValidatedAssetVersion")
|
||||
s.ValidatedAssetVersion.Encode(e)
|
||||
}
|
||||
}
|
||||
{
|
||||
e.FieldStart("Completed")
|
||||
e.Bool(s.Completed)
|
||||
@@ -744,7 +756,7 @@ func (s *Mapfix) encodeFields(e *jx.Encoder) {
|
||||
}
|
||||
}
|
||||
|
||||
var jsonFieldsNameOfMapfix = [13]string{
|
||||
var jsonFieldsNameOfMapfix = [15]string{
|
||||
0: "ID",
|
||||
1: "DisplayName",
|
||||
2: "Creator",
|
||||
@@ -754,10 +766,12 @@ var jsonFieldsNameOfMapfix = [13]string{
|
||||
6: "Submitter",
|
||||
7: "AssetID",
|
||||
8: "AssetVersion",
|
||||
9: "Completed",
|
||||
10: "TargetAssetID",
|
||||
11: "StatusID",
|
||||
12: "Description",
|
||||
9: "ValidatedAssetID",
|
||||
10: "ValidatedAssetVersion",
|
||||
11: "Completed",
|
||||
12: "TargetAssetID",
|
||||
13: "StatusID",
|
||||
14: "Description",
|
||||
}
|
||||
|
||||
// Decode decodes Mapfix from json.
|
||||
@@ -877,8 +891,28 @@ func (s *Mapfix) Decode(d *jx.Decoder) error {
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"AssetVersion\"")
|
||||
}
|
||||
case "ValidatedAssetID":
|
||||
if err := func() error {
|
||||
s.ValidatedAssetID.Reset()
|
||||
if err := s.ValidatedAssetID.Decode(d); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"ValidatedAssetID\"")
|
||||
}
|
||||
case "ValidatedAssetVersion":
|
||||
if err := func() error {
|
||||
s.ValidatedAssetVersion.Reset()
|
||||
if err := s.ValidatedAssetVersion.Decode(d); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return errors.Wrap(err, "decode field \"ValidatedAssetVersion\"")
|
||||
}
|
||||
case "Completed":
|
||||
requiredBitSet[1] |= 1 << 1
|
||||
requiredBitSet[1] |= 1 << 3
|
||||
if err := func() error {
|
||||
v, err := d.Bool()
|
||||
s.Completed = bool(v)
|
||||
@@ -890,7 +924,7 @@ func (s *Mapfix) Decode(d *jx.Decoder) error {
|
||||
return errors.Wrap(err, "decode field \"Completed\"")
|
||||
}
|
||||
case "TargetAssetID":
|
||||
requiredBitSet[1] |= 1 << 2
|
||||
requiredBitSet[1] |= 1 << 4
|
||||
if err := func() error {
|
||||
v, err := d.Int64()
|
||||
s.TargetAssetID = int64(v)
|
||||
@@ -902,7 +936,7 @@ func (s *Mapfix) Decode(d *jx.Decoder) error {
|
||||
return errors.Wrap(err, "decode field \"TargetAssetID\"")
|
||||
}
|
||||
case "StatusID":
|
||||
requiredBitSet[1] |= 1 << 3
|
||||
requiredBitSet[1] |= 1 << 5
|
||||
if err := func() error {
|
||||
v, err := d.Int32()
|
||||
s.StatusID = int32(v)
|
||||
@@ -914,7 +948,7 @@ func (s *Mapfix) Decode(d *jx.Decoder) error {
|
||||
return errors.Wrap(err, "decode field \"StatusID\"")
|
||||
}
|
||||
case "Description":
|
||||
requiredBitSet[1] |= 1 << 4
|
||||
requiredBitSet[1] |= 1 << 6
|
||||
if err := func() error {
|
||||
v, err := d.Str()
|
||||
s.Description = string(v)
|
||||
@@ -936,7 +970,7 @@ func (s *Mapfix) Decode(d *jx.Decoder) error {
|
||||
var failures []validate.FieldError
|
||||
for i, mask := range [2]uint8{
|
||||
0b11111111,
|
||||
0b00011111,
|
||||
0b01111001,
|
||||
} {
|
||||
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
|
||||
// Mask only required fields and check equality to mask using XOR.
|
||||
|
||||
@@ -12,10 +12,12 @@ const (
|
||||
ActionMapfixResetSubmittingOperation OperationName = "ActionMapfixResetSubmitting"
|
||||
ActionMapfixRetryValidateOperation OperationName = "ActionMapfixRetryValidate"
|
||||
ActionMapfixRevokeOperation OperationName = "ActionMapfixRevoke"
|
||||
ActionMapfixTriggerReleaseOperation OperationName = "ActionMapfixTriggerRelease"
|
||||
ActionMapfixTriggerSubmitOperation OperationName = "ActionMapfixTriggerSubmit"
|
||||
ActionMapfixTriggerSubmitUncheckedOperation OperationName = "ActionMapfixTriggerSubmitUnchecked"
|
||||
ActionMapfixTriggerUploadOperation OperationName = "ActionMapfixTriggerUpload"
|
||||
ActionMapfixTriggerValidateOperation OperationName = "ActionMapfixTriggerValidate"
|
||||
ActionMapfixUploadedOperation OperationName = "ActionMapfixUploaded"
|
||||
ActionMapfixValidatedOperation OperationName = "ActionMapfixValidated"
|
||||
ActionSubmissionAcceptedOperation OperationName = "ActionSubmissionAccepted"
|
||||
ActionSubmissionRejectOperation OperationName = "ActionSubmissionReject"
|
||||
@@ -51,6 +53,7 @@ const (
|
||||
ListScriptsOperation OperationName = "ListScripts"
|
||||
ListSubmissionAuditEventsOperation OperationName = "ListSubmissionAuditEvents"
|
||||
ListSubmissionsOperation OperationName = "ListSubmissions"
|
||||
MigrateMapfixesOperation OperationName = "MigrateMapfixes"
|
||||
ReleaseSubmissionsOperation OperationName = "ReleaseSubmissions"
|
||||
SessionRolesOperation OperationName = "SessionRoles"
|
||||
SessionUserOperation OperationName = "SessionUser"
|
||||
|
||||
@@ -513,6 +513,89 @@ func decodeActionMapfixRevokeParams(args [1]string, argsEscaped bool, r *http.Re
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerReleaseParams is parameters of actionMapfixTriggerRelease operation.
|
||||
type ActionMapfixTriggerReleaseParams struct {
|
||||
// The unique identifier for a mapfix.
|
||||
MapfixID int64
|
||||
}
|
||||
|
||||
func unpackActionMapfixTriggerReleaseParams(packed middleware.Parameters) (params ActionMapfixTriggerReleaseParams) {
|
||||
{
|
||||
key := middleware.ParameterKey{
|
||||
Name: "MapfixID",
|
||||
In: "path",
|
||||
}
|
||||
params.MapfixID = packed[key].(int64)
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
func decodeActionMapfixTriggerReleaseParams(args [1]string, argsEscaped bool, r *http.Request) (params ActionMapfixTriggerReleaseParams, _ error) {
|
||||
// Decode path: MapfixID.
|
||||
if err := func() error {
|
||||
param := args[0]
|
||||
if argsEscaped {
|
||||
unescaped, err := url.PathUnescape(args[0])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unescape path")
|
||||
}
|
||||
param = unescaped
|
||||
}
|
||||
if len(param) > 0 {
|
||||
d := uri.NewPathDecoder(uri.PathDecoderConfig{
|
||||
Param: "MapfixID",
|
||||
Value: param,
|
||||
Style: uri.PathStyleSimple,
|
||||
Explode: false,
|
||||
})
|
||||
|
||||
if err := func() error {
|
||||
val, err := d.DecodeValue()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := conv.ToInt64(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
params.MapfixID = c
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := func() error {
|
||||
if err := (validate.Int{
|
||||
MinSet: true,
|
||||
Min: 0,
|
||||
MaxSet: false,
|
||||
Max: 0,
|
||||
MinExclusive: false,
|
||||
MaxExclusive: false,
|
||||
MultipleOfSet: false,
|
||||
MultipleOf: 0,
|
||||
}).Validate(int64(params.MapfixID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return validate.ErrFieldRequired
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return params, &ogenerrors.DecodeParamError{
|
||||
Name: "MapfixID",
|
||||
In: "path",
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerSubmitParams is parameters of actionMapfixTriggerSubmit operation.
|
||||
type ActionMapfixTriggerSubmitParams struct {
|
||||
// The unique identifier for a mapfix.
|
||||
@@ -845,6 +928,89 @@ func decodeActionMapfixTriggerValidateParams(args [1]string, argsEscaped bool, r
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// ActionMapfixUploadedParams is parameters of actionMapfixUploaded operation.
|
||||
type ActionMapfixUploadedParams struct {
|
||||
// The unique identifier for a mapfix.
|
||||
MapfixID int64
|
||||
}
|
||||
|
||||
func unpackActionMapfixUploadedParams(packed middleware.Parameters) (params ActionMapfixUploadedParams) {
|
||||
{
|
||||
key := middleware.ParameterKey{
|
||||
Name: "MapfixID",
|
||||
In: "path",
|
||||
}
|
||||
params.MapfixID = packed[key].(int64)
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
func decodeActionMapfixUploadedParams(args [1]string, argsEscaped bool, r *http.Request) (params ActionMapfixUploadedParams, _ error) {
|
||||
// Decode path: MapfixID.
|
||||
if err := func() error {
|
||||
param := args[0]
|
||||
if argsEscaped {
|
||||
unescaped, err := url.PathUnescape(args[0])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unescape path")
|
||||
}
|
||||
param = unescaped
|
||||
}
|
||||
if len(param) > 0 {
|
||||
d := uri.NewPathDecoder(uri.PathDecoderConfig{
|
||||
Param: "MapfixID",
|
||||
Value: param,
|
||||
Style: uri.PathStyleSimple,
|
||||
Explode: false,
|
||||
})
|
||||
|
||||
if err := func() error {
|
||||
val, err := d.DecodeValue()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := conv.ToInt64(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
params.MapfixID = c
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := func() error {
|
||||
if err := (validate.Int{
|
||||
MinSet: true,
|
||||
Min: 0,
|
||||
MaxSet: false,
|
||||
Max: 0,
|
||||
MinExclusive: false,
|
||||
MaxExclusive: false,
|
||||
MultipleOfSet: false,
|
||||
MultipleOf: 0,
|
||||
}).Validate(int64(params.MapfixID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return validate.ErrFieldRequired
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return params, &ogenerrors.DecodeParamError{
|
||||
Name: "MapfixID",
|
||||
In: "path",
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// ActionMapfixValidatedParams is parameters of actionMapfixValidated operation.
|
||||
type ActionMapfixValidatedParams struct {
|
||||
// The unique identifier for a mapfix.
|
||||
@@ -2972,6 +3138,7 @@ type ListMapfixesParams struct {
|
||||
Sort OptInt32
|
||||
Submitter OptInt64
|
||||
AssetID OptInt64
|
||||
AssetVersion OptInt64
|
||||
TargetAssetID OptInt64
|
||||
// // Phase: Creation * `0` - UnderConstruction * `1` - ChangesRequested
|
||||
// // Phase: Review * `2` - Submitting * `3` - Submitted
|
||||
@@ -3051,6 +3218,15 @@ func unpackListMapfixesParams(packed middleware.Parameters) (params ListMapfixes
|
||||
params.AssetID = v.(OptInt64)
|
||||
}
|
||||
}
|
||||
{
|
||||
key := middleware.ParameterKey{
|
||||
Name: "AssetVersion",
|
||||
In: "query",
|
||||
}
|
||||
if v, ok := packed[key]; ok {
|
||||
params.AssetVersion = v.(OptInt64)
|
||||
}
|
||||
}
|
||||
{
|
||||
key := middleware.ParameterKey{
|
||||
Name: "TargetAssetID",
|
||||
@@ -3568,6 +3744,71 @@ func decodeListMapfixesParams(args [0]string, argsEscaped bool, r *http.Request)
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
// Decode query: AssetVersion.
|
||||
if err := func() error {
|
||||
cfg := uri.QueryParameterDecodingConfig{
|
||||
Name: "AssetVersion",
|
||||
Style: uri.QueryStyleForm,
|
||||
Explode: true,
|
||||
}
|
||||
|
||||
if err := q.HasParam(cfg); err == nil {
|
||||
if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
|
||||
var paramsDotAssetVersionVal int64
|
||||
if err := func() error {
|
||||
val, err := d.DecodeValue()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := conv.ToInt64(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
paramsDotAssetVersionVal = c
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
params.AssetVersion.SetTo(paramsDotAssetVersionVal)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := func() error {
|
||||
if value, ok := params.AssetVersion.Get(); ok {
|
||||
if err := func() error {
|
||||
if err := (validate.Int{
|
||||
MinSet: true,
|
||||
Min: 0,
|
||||
MaxSet: false,
|
||||
Max: 0,
|
||||
MinExclusive: false,
|
||||
MaxExclusive: false,
|
||||
MultipleOfSet: false,
|
||||
MultipleOf: 0,
|
||||
}).Validate(int64(value)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return params, &ogenerrors.DecodeParamError{
|
||||
Name: "AssetVersion",
|
||||
In: "query",
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
// Decode query: TargetAssetID.
|
||||
if err := func() error {
|
||||
cfg := uri.QueryParameterDecodingConfig{
|
||||
@@ -5221,6 +5462,7 @@ type ListSubmissionsParams struct {
|
||||
Sort OptInt32
|
||||
Submitter OptInt64
|
||||
AssetID OptInt64
|
||||
AssetVersion OptInt64
|
||||
UploadedAssetID OptInt64
|
||||
// // Phase: Creation * `0` - UnderConstruction * `1` - ChangesRequested
|
||||
// // Phase: Review * `2` - Submitting * `3` - Submitted
|
||||
@@ -5300,6 +5542,15 @@ func unpackListSubmissionsParams(packed middleware.Parameters) (params ListSubmi
|
||||
params.AssetID = v.(OptInt64)
|
||||
}
|
||||
}
|
||||
{
|
||||
key := middleware.ParameterKey{
|
||||
Name: "AssetVersion",
|
||||
In: "query",
|
||||
}
|
||||
if v, ok := packed[key]; ok {
|
||||
params.AssetVersion = v.(OptInt64)
|
||||
}
|
||||
}
|
||||
{
|
||||
key := middleware.ParameterKey{
|
||||
Name: "UploadedAssetID",
|
||||
@@ -5817,6 +6068,71 @@ func decodeListSubmissionsParams(args [0]string, argsEscaped bool, r *http.Reque
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
// Decode query: AssetVersion.
|
||||
if err := func() error {
|
||||
cfg := uri.QueryParameterDecodingConfig{
|
||||
Name: "AssetVersion",
|
||||
Style: uri.QueryStyleForm,
|
||||
Explode: true,
|
||||
}
|
||||
|
||||
if err := q.HasParam(cfg); err == nil {
|
||||
if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
|
||||
var paramsDotAssetVersionVal int64
|
||||
if err := func() error {
|
||||
val, err := d.DecodeValue()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := conv.ToInt64(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
paramsDotAssetVersionVal = c
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
params.AssetVersion.SetTo(paramsDotAssetVersionVal)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := func() error {
|
||||
if value, ok := params.AssetVersion.Get(); ok {
|
||||
if err := func() error {
|
||||
if err := (validate.Int{
|
||||
MinSet: true,
|
||||
Min: 0,
|
||||
MaxSet: false,
|
||||
Max: 0,
|
||||
MinExclusive: false,
|
||||
MaxExclusive: false,
|
||||
MultipleOfSet: false,
|
||||
MultipleOf: 0,
|
||||
}).Validate(int64(value)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return params, &ogenerrors.DecodeParamError{
|
||||
Name: "AssetVersion",
|
||||
In: "query",
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
// Decode query: UploadedAssetID.
|
||||
if err := func() error {
|
||||
cfg := uri.QueryParameterDecodingConfig{
|
||||
|
||||
@@ -376,6 +376,66 @@ func decodeActionMapfixRevokeResponse(resp *http.Response) (res *ActionMapfixRev
|
||||
return res, errors.Wrap(defRes, "error")
|
||||
}
|
||||
|
||||
func decodeActionMapfixTriggerReleaseResponse(resp *http.Response) (res *ActionMapfixTriggerReleaseNoContent, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 204:
|
||||
// Code 204.
|
||||
return &ActionMapfixTriggerReleaseNoContent{}, nil
|
||||
}
|
||||
// Convenient error response.
|
||||
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "parse media type")
|
||||
}
|
||||
switch {
|
||||
case ct == "application/json":
|
||||
buf, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
d := jx.DecodeBytes(buf)
|
||||
|
||||
var response Error
|
||||
if err := func() error {
|
||||
if err := response.Decode(d); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Skip(); err != io.EOF {
|
||||
return errors.New("unexpected trailing data")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
err = &ogenerrors.DecodeBodyError{
|
||||
ContentType: ct,
|
||||
Body: buf,
|
||||
Err: err,
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
// Validate response.
|
||||
if err := func() error {
|
||||
if err := response.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return res, errors.Wrap(err, "validate")
|
||||
}
|
||||
return &ErrorStatusCode{
|
||||
StatusCode: resp.StatusCode,
|
||||
Response: response,
|
||||
}, nil
|
||||
default:
|
||||
return res, validate.InvalidContentType(ct)
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
|
||||
}
|
||||
return res, errors.Wrap(defRes, "error")
|
||||
}
|
||||
|
||||
func decodeActionMapfixTriggerSubmitResponse(resp *http.Response) (res *ActionMapfixTriggerSubmitNoContent, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 204:
|
||||
@@ -616,6 +676,66 @@ func decodeActionMapfixTriggerValidateResponse(resp *http.Response) (res *Action
|
||||
return res, errors.Wrap(defRes, "error")
|
||||
}
|
||||
|
||||
func decodeActionMapfixUploadedResponse(resp *http.Response) (res *ActionMapfixUploadedNoContent, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 204:
|
||||
// Code 204.
|
||||
return &ActionMapfixUploadedNoContent{}, nil
|
||||
}
|
||||
// Convenient error response.
|
||||
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "parse media type")
|
||||
}
|
||||
switch {
|
||||
case ct == "application/json":
|
||||
buf, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
d := jx.DecodeBytes(buf)
|
||||
|
||||
var response Error
|
||||
if err := func() error {
|
||||
if err := response.Decode(d); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Skip(); err != io.EOF {
|
||||
return errors.New("unexpected trailing data")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
err = &ogenerrors.DecodeBodyError{
|
||||
ContentType: ct,
|
||||
Body: buf,
|
||||
Err: err,
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
// Validate response.
|
||||
if err := func() error {
|
||||
if err := response.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return res, errors.Wrap(err, "validate")
|
||||
}
|
||||
return &ErrorStatusCode{
|
||||
StatusCode: resp.StatusCode,
|
||||
Response: response,
|
||||
}, nil
|
||||
default:
|
||||
return res, validate.InvalidContentType(ct)
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
|
||||
}
|
||||
return res, errors.Wrap(defRes, "error")
|
||||
}
|
||||
|
||||
func decodeActionMapfixValidatedResponse(resp *http.Response) (res *ActionMapfixValidatedNoContent, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 204:
|
||||
@@ -3595,6 +3715,66 @@ func decodeListSubmissionsResponse(resp *http.Response) (res *Submissions, _ err
|
||||
return res, errors.Wrap(defRes, "error")
|
||||
}
|
||||
|
||||
func decodeMigrateMapfixesResponse(resp *http.Response) (res *MigrateMapfixesNoContent, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 204:
|
||||
// Code 204.
|
||||
return &MigrateMapfixesNoContent{}, nil
|
||||
}
|
||||
// Convenient error response.
|
||||
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
return res, errors.Wrap(err, "parse media type")
|
||||
}
|
||||
switch {
|
||||
case ct == "application/json":
|
||||
buf, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
d := jx.DecodeBytes(buf)
|
||||
|
||||
var response Error
|
||||
if err := func() error {
|
||||
if err := response.Decode(d); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Skip(); err != io.EOF {
|
||||
return errors.New("unexpected trailing data")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
err = &ogenerrors.DecodeBodyError{
|
||||
ContentType: ct,
|
||||
Body: buf,
|
||||
Err: err,
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
// Validate response.
|
||||
if err := func() error {
|
||||
if err := response.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return res, errors.Wrap(err, "validate")
|
||||
}
|
||||
return &ErrorStatusCode{
|
||||
StatusCode: resp.StatusCode,
|
||||
Response: response,
|
||||
}, nil
|
||||
default:
|
||||
return res, validate.InvalidContentType(ct)
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
|
||||
}
|
||||
return res, errors.Wrap(defRes, "error")
|
||||
}
|
||||
|
||||
func decodeReleaseSubmissionsResponse(resp *http.Response) (res *ReleaseSubmissionsCreated, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 201:
|
||||
|
||||
@@ -56,6 +56,13 @@ func encodeActionMapfixRevokeResponse(response *ActionMapfixRevokeNoContent, w h
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionMapfixTriggerReleaseResponse(response *ActionMapfixTriggerReleaseNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionMapfixTriggerSubmitResponse(response *ActionMapfixTriggerSubmitNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
@@ -84,6 +91,13 @@ func encodeActionMapfixTriggerValidateResponse(response *ActionMapfixTriggerVali
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionMapfixUploadedResponse(response *ActionMapfixUploadedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionMapfixValidatedResponse(response *ActionMapfixValidatedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
@@ -484,6 +498,13 @@ func encodeListSubmissionsResponse(response *Submissions, w http.ResponseWriter,
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeMigrateMapfixesResponse(response *MigrateMapfixesNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeReleaseSubmissionsResponse(response *ReleaseSubmissionsCreated, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(201)
|
||||
span.SetStatus(codes.Ok, http.StatusText(201))
|
||||
|
||||
@@ -102,6 +102,32 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
break
|
||||
}
|
||||
|
||||
if len(elem) == 0 {
|
||||
break
|
||||
}
|
||||
switch elem[0] {
|
||||
case 'm': // Prefix: "migrate"
|
||||
origElem := elem
|
||||
if l := len("migrate"); len(elem) >= l && elem[0:l] == "migrate" {
|
||||
elem = elem[l:]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
||||
if len(elem) == 0 {
|
||||
// Leaf node.
|
||||
switch r.Method {
|
||||
case "POST":
|
||||
s.handleMigrateMapfixesRequest([0]string{}, elemIsEscaped, w, r)
|
||||
default:
|
||||
s.notAllowed(w, r, "POST")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
elem = origElem
|
||||
}
|
||||
// Param: "MapfixID"
|
||||
// Match until "/"
|
||||
idx := strings.IndexByte(elem, '/')
|
||||
@@ -318,6 +344,28 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
break
|
||||
}
|
||||
switch elem[0] {
|
||||
case 'r': // Prefix: "releasing"
|
||||
|
||||
if l := len("releasing"); len(elem) >= l && elem[0:l] == "releasing" {
|
||||
elem = elem[l:]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
||||
if len(elem) == 0 {
|
||||
// Leaf node.
|
||||
switch r.Method {
|
||||
case "POST":
|
||||
s.handleActionMapfixUploadedRequest([1]string{
|
||||
args[0],
|
||||
}, elemIsEscaped, w, r)
|
||||
default:
|
||||
s.notAllowed(w, r, "POST")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
case 's': // Prefix: "submitting"
|
||||
|
||||
if l := len("submitting"); len(elem) >= l && elem[0:l] == "submitting" {
|
||||
@@ -444,6 +492,28 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
break
|
||||
}
|
||||
switch elem[0] {
|
||||
case 'r': // Prefix: "release"
|
||||
|
||||
if l := len("release"); len(elem) >= l && elem[0:l] == "release" {
|
||||
elem = elem[l:]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
||||
if len(elem) == 0 {
|
||||
// Leaf node.
|
||||
switch r.Method {
|
||||
case "POST":
|
||||
s.handleActionMapfixTriggerReleaseRequest([1]string{
|
||||
args[0],
|
||||
}, elemIsEscaped, w, r)
|
||||
default:
|
||||
s.notAllowed(w, r, "POST")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
case 's': // Prefix: "submit"
|
||||
|
||||
if l := len("submit"); len(elem) >= l && elem[0:l] == "submit" {
|
||||
@@ -1532,6 +1602,36 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
||||
break
|
||||
}
|
||||
|
||||
if len(elem) == 0 {
|
||||
break
|
||||
}
|
||||
switch elem[0] {
|
||||
case 'm': // Prefix: "migrate"
|
||||
origElem := elem
|
||||
if l := len("migrate"); len(elem) >= l && elem[0:l] == "migrate" {
|
||||
elem = elem[l:]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
||||
if len(elem) == 0 {
|
||||
// Leaf node.
|
||||
switch method {
|
||||
case "POST":
|
||||
r.name = MigrateMapfixesOperation
|
||||
r.summary = "Perform the Uploaded -> Released migration."
|
||||
r.operationID = "migrateMapfixes"
|
||||
r.pathPattern = "/mapfixes/migrate"
|
||||
r.args = args
|
||||
r.count = 0
|
||||
return r, true
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
elem = origElem
|
||||
}
|
||||
// Param: "MapfixID"
|
||||
// Match until "/"
|
||||
idx := strings.IndexByte(elem, '/')
|
||||
@@ -1762,6 +1862,30 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
||||
break
|
||||
}
|
||||
switch elem[0] {
|
||||
case 'r': // Prefix: "releasing"
|
||||
|
||||
if l := len("releasing"); len(elem) >= l && elem[0:l] == "releasing" {
|
||||
elem = elem[l:]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
||||
if len(elem) == 0 {
|
||||
// Leaf node.
|
||||
switch method {
|
||||
case "POST":
|
||||
r.name = ActionMapfixUploadedOperation
|
||||
r.summary = "Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded"
|
||||
r.operationID = "actionMapfixUploaded"
|
||||
r.pathPattern = "/mapfixes/{MapfixID}/status/reset-releasing"
|
||||
r.args = args
|
||||
r.count = 1
|
||||
return r, true
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
case 's': // Prefix: "submitting"
|
||||
|
||||
if l := len("submitting"); len(elem) >= l && elem[0:l] == "submitting" {
|
||||
@@ -1799,7 +1923,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
||||
switch method {
|
||||
case "POST":
|
||||
r.name = ActionMapfixValidatedOperation
|
||||
r.summary = "Role Admin manually resets uploading softlock and changes status from Uploading -> Validated"
|
||||
r.summary = "Role MapfixUpload manually resets uploading softlock and changes status from Uploading -> Validated"
|
||||
r.operationID = "actionMapfixValidated"
|
||||
r.pathPattern = "/mapfixes/{MapfixID}/status/reset-uploading"
|
||||
r.args = args
|
||||
@@ -1898,6 +2022,30 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
||||
break
|
||||
}
|
||||
switch elem[0] {
|
||||
case 'r': // Prefix: "release"
|
||||
|
||||
if l := len("release"); len(elem) >= l && elem[0:l] == "release" {
|
||||
elem = elem[l:]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
||||
if len(elem) == 0 {
|
||||
// Leaf node.
|
||||
switch method {
|
||||
case "POST":
|
||||
r.name = ActionMapfixTriggerReleaseOperation
|
||||
r.summary = "Role MapfixUpload changes status from Uploaded -> Releasing"
|
||||
r.operationID = "actionMapfixTriggerRelease"
|
||||
r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-release"
|
||||
r.args = args
|
||||
r.count = 1
|
||||
return r, true
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
case 's': // Prefix: "submit"
|
||||
|
||||
if l := len("submit"); len(elem) >= l && elem[0:l] == "submit" {
|
||||
@@ -1960,7 +2108,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
||||
switch method {
|
||||
case "POST":
|
||||
r.name = ActionMapfixTriggerUploadOperation
|
||||
r.summary = "Role Admin changes status from Validated -> Uploading"
|
||||
r.summary = "Role MapfixUpload changes status from Validated -> Uploading"
|
||||
r.operationID = "actionMapfixTriggerUpload"
|
||||
r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-upload"
|
||||
r.args = args
|
||||
@@ -2136,7 +2284,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
||||
switch method {
|
||||
case "POST":
|
||||
r.name = ReleaseSubmissionsOperation
|
||||
r.summary = "Release a set of uploaded maps"
|
||||
r.summary = "Release a set of uploaded maps. Role SubmissionRelease"
|
||||
r.operationID = "releaseSubmissions"
|
||||
r.pathPattern = "/release-submissions"
|
||||
r.args = args
|
||||
@@ -2753,7 +2901,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
||||
switch method {
|
||||
case "POST":
|
||||
r.name = ActionSubmissionValidatedOperation
|
||||
r.summary = "Role Admin manually resets uploading softlock and changes status from Uploading -> Validated"
|
||||
r.summary = "Role SubmissionUpload manually resets uploading softlock and changes status from Uploading -> Validated"
|
||||
r.operationID = "actionSubmissionValidated"
|
||||
r.pathPattern = "/submissions/{SubmissionID}/status/reset-uploading"
|
||||
r.args = args
|
||||
@@ -2914,7 +3062,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
||||
switch method {
|
||||
case "POST":
|
||||
r.name = ActionSubmissionTriggerUploadOperation
|
||||
r.summary = "Role Admin changes status from Validated -> Uploading"
|
||||
r.summary = "Role SubmissionUpload changes status from Validated -> Uploading"
|
||||
r.operationID = "actionSubmissionTriggerUpload"
|
||||
r.pathPattern = "/submissions/{SubmissionID}/status/trigger-upload"
|
||||
r.args = args
|
||||
|
||||
@@ -32,6 +32,9 @@ type ActionMapfixRetryValidateNoContent struct{}
|
||||
// ActionMapfixRevokeNoContent is response for ActionMapfixRevoke operation.
|
||||
type ActionMapfixRevokeNoContent struct{}
|
||||
|
||||
// ActionMapfixTriggerReleaseNoContent is response for ActionMapfixTriggerRelease operation.
|
||||
type ActionMapfixTriggerReleaseNoContent struct{}
|
||||
|
||||
// ActionMapfixTriggerSubmitNoContent is response for ActionMapfixTriggerSubmit operation.
|
||||
type ActionMapfixTriggerSubmitNoContent struct{}
|
||||
|
||||
@@ -44,6 +47,9 @@ type ActionMapfixTriggerUploadNoContent struct{}
|
||||
// ActionMapfixTriggerValidateNoContent is response for ActionMapfixTriggerValidate operation.
|
||||
type ActionMapfixTriggerValidateNoContent struct{}
|
||||
|
||||
// ActionMapfixUploadedNoContent is response for ActionMapfixUploaded operation.
|
||||
type ActionMapfixUploadedNoContent struct{}
|
||||
|
||||
// ActionMapfixValidatedNoContent is response for ActionMapfixValidated operation.
|
||||
type ActionMapfixValidatedNoContent struct{}
|
||||
|
||||
@@ -456,19 +462,21 @@ func (s *Map) SetModes(val uint32) {
|
||||
|
||||
// Ref: #/components/schemas/Mapfix
|
||||
type Mapfix struct {
|
||||
ID int64 `json:"ID"`
|
||||
DisplayName string `json:"DisplayName"`
|
||||
Creator string `json:"Creator"`
|
||||
GameID int32 `json:"GameID"`
|
||||
CreatedAt int64 `json:"CreatedAt"`
|
||||
UpdatedAt int64 `json:"UpdatedAt"`
|
||||
Submitter int64 `json:"Submitter"`
|
||||
AssetID int64 `json:"AssetID"`
|
||||
AssetVersion int64 `json:"AssetVersion"`
|
||||
Completed bool `json:"Completed"`
|
||||
TargetAssetID int64 `json:"TargetAssetID"`
|
||||
StatusID int32 `json:"StatusID"`
|
||||
Description string `json:"Description"`
|
||||
ID int64 `json:"ID"`
|
||||
DisplayName string `json:"DisplayName"`
|
||||
Creator string `json:"Creator"`
|
||||
GameID int32 `json:"GameID"`
|
||||
CreatedAt int64 `json:"CreatedAt"`
|
||||
UpdatedAt int64 `json:"UpdatedAt"`
|
||||
Submitter int64 `json:"Submitter"`
|
||||
AssetID int64 `json:"AssetID"`
|
||||
AssetVersion int64 `json:"AssetVersion"`
|
||||
ValidatedAssetID OptInt64 `json:"ValidatedAssetID"`
|
||||
ValidatedAssetVersion OptInt64 `json:"ValidatedAssetVersion"`
|
||||
Completed bool `json:"Completed"`
|
||||
TargetAssetID int64 `json:"TargetAssetID"`
|
||||
StatusID int32 `json:"StatusID"`
|
||||
Description string `json:"Description"`
|
||||
}
|
||||
|
||||
// GetID returns the value of ID.
|
||||
@@ -516,6 +524,16 @@ func (s *Mapfix) GetAssetVersion() int64 {
|
||||
return s.AssetVersion
|
||||
}
|
||||
|
||||
// GetValidatedAssetID returns the value of ValidatedAssetID.
|
||||
func (s *Mapfix) GetValidatedAssetID() OptInt64 {
|
||||
return s.ValidatedAssetID
|
||||
}
|
||||
|
||||
// GetValidatedAssetVersion returns the value of ValidatedAssetVersion.
|
||||
func (s *Mapfix) GetValidatedAssetVersion() OptInt64 {
|
||||
return s.ValidatedAssetVersion
|
||||
}
|
||||
|
||||
// GetCompleted returns the value of Completed.
|
||||
func (s *Mapfix) GetCompleted() bool {
|
||||
return s.Completed
|
||||
@@ -581,6 +599,16 @@ func (s *Mapfix) SetAssetVersion(val int64) {
|
||||
s.AssetVersion = val
|
||||
}
|
||||
|
||||
// SetValidatedAssetID sets the value of ValidatedAssetID.
|
||||
func (s *Mapfix) SetValidatedAssetID(val OptInt64) {
|
||||
s.ValidatedAssetID = val
|
||||
}
|
||||
|
||||
// SetValidatedAssetVersion sets the value of ValidatedAssetVersion.
|
||||
func (s *Mapfix) SetValidatedAssetVersion(val OptInt64) {
|
||||
s.ValidatedAssetVersion = val
|
||||
}
|
||||
|
||||
// SetCompleted sets the value of Completed.
|
||||
func (s *Mapfix) SetCompleted(val bool) {
|
||||
s.Completed = val
|
||||
@@ -664,6 +692,9 @@ func (s *Mapfixes) SetMapfixes(val []Mapfix) {
|
||||
s.Mapfixes = val
|
||||
}
|
||||
|
||||
// MigrateMapfixesNoContent is response for MigrateMapfixes operation.
|
||||
type MigrateMapfixesNoContent struct{}
|
||||
|
||||
// Ref: #/components/schemas/Operation
|
||||
type Operation struct {
|
||||
OperationID int32 `json:"OperationID"`
|
||||
|
||||
@@ -40,10 +40,12 @@ var operationRolesCookieAuth = map[string][]string{
|
||||
ActionMapfixResetSubmittingOperation: []string{},
|
||||
ActionMapfixRetryValidateOperation: []string{},
|
||||
ActionMapfixRevokeOperation: []string{},
|
||||
ActionMapfixTriggerReleaseOperation: []string{},
|
||||
ActionMapfixTriggerSubmitOperation: []string{},
|
||||
ActionMapfixTriggerSubmitUncheckedOperation: []string{},
|
||||
ActionMapfixTriggerUploadOperation: []string{},
|
||||
ActionMapfixTriggerValidateOperation: []string{},
|
||||
ActionMapfixUploadedOperation: []string{},
|
||||
ActionMapfixValidatedOperation: []string{},
|
||||
ActionSubmissionAcceptedOperation: []string{},
|
||||
ActionSubmissionRejectOperation: []string{},
|
||||
@@ -67,6 +69,7 @@ var operationRolesCookieAuth = map[string][]string{
|
||||
DeleteScriptPolicyOperation: []string{},
|
||||
DownloadMapAssetOperation: []string{},
|
||||
GetOperationOperation: []string{},
|
||||
MigrateMapfixesOperation: []string{},
|
||||
ReleaseSubmissionsOperation: []string{},
|
||||
SessionRolesOperation: []string{},
|
||||
SessionUserOperation: []string{},
|
||||
|
||||
@@ -45,6 +45,12 @@ type Handler interface {
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/revoke
|
||||
ActionMapfixRevoke(ctx context.Context, params ActionMapfixRevokeParams) error
|
||||
// ActionMapfixTriggerRelease implements actionMapfixTriggerRelease operation.
|
||||
//
|
||||
// Role MapfixUpload changes status from Uploaded -> Releasing.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-release
|
||||
ActionMapfixTriggerRelease(ctx context.Context, params ActionMapfixTriggerReleaseParams) error
|
||||
// ActionMapfixTriggerSubmit implements actionMapfixTriggerSubmit operation.
|
||||
//
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||
@@ -59,7 +65,7 @@ type Handler interface {
|
||||
ActionMapfixTriggerSubmitUnchecked(ctx context.Context, params ActionMapfixTriggerSubmitUncheckedParams) error
|
||||
// ActionMapfixTriggerUpload implements actionMapfixTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
// Role MapfixUpload changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-upload
|
||||
ActionMapfixTriggerUpload(ctx context.Context, params ActionMapfixTriggerUploadParams) error
|
||||
@@ -69,9 +75,15 @@ type Handler interface {
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-validate
|
||||
ActionMapfixTriggerValidate(ctx context.Context, params ActionMapfixTriggerValidateParams) error
|
||||
// ActionMapfixUploaded implements actionMapfixUploaded operation.
|
||||
//
|
||||
// Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-releasing
|
||||
ActionMapfixUploaded(ctx context.Context, params ActionMapfixUploadedParams) error
|
||||
// ActionMapfixValidated implements actionMapfixValidated operation.
|
||||
//
|
||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
// Role MapfixUpload manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-uploading
|
||||
ActionMapfixValidated(ctx context.Context, params ActionMapfixValidatedParams) error
|
||||
@@ -126,7 +138,7 @@ type Handler interface {
|
||||
ActionSubmissionTriggerSubmitUnchecked(ctx context.Context, params ActionSubmissionTriggerSubmitUncheckedParams) error
|
||||
// ActionSubmissionTriggerUpload implements actionSubmissionTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
// Role SubmissionUpload changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/trigger-upload
|
||||
ActionSubmissionTriggerUpload(ctx context.Context, params ActionSubmissionTriggerUploadParams) error
|
||||
@@ -138,7 +150,8 @@ type Handler interface {
|
||||
ActionSubmissionTriggerValidate(ctx context.Context, params ActionSubmissionTriggerValidateParams) error
|
||||
// ActionSubmissionValidated implements actionSubmissionValidated operation.
|
||||
//
|
||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
// Role SubmissionUpload manually resets uploading softlock and changes status from Uploading ->
|
||||
// Validated.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/reset-uploading
|
||||
ActionSubmissionValidated(ctx context.Context, params ActionSubmissionValidatedParams) error
|
||||
@@ -280,9 +293,15 @@ type Handler interface {
|
||||
//
|
||||
// GET /submissions
|
||||
ListSubmissions(ctx context.Context, params ListSubmissionsParams) (*Submissions, error)
|
||||
// MigrateMapfixes implements migrateMapfixes operation.
|
||||
//
|
||||
// Perform the Uploaded -> Released migration.
|
||||
//
|
||||
// POST /mapfixes/migrate
|
||||
MigrateMapfixes(ctx context.Context) error
|
||||
// ReleaseSubmissions implements releaseSubmissions operation.
|
||||
//
|
||||
// Release a set of uploaded maps.
|
||||
// Release a set of uploaded maps. Role SubmissionRelease.
|
||||
//
|
||||
// POST /release-submissions
|
||||
ReleaseSubmissions(ctx context.Context, req []ReleaseInfo) error
|
||||
|
||||
@@ -68,6 +68,15 @@ func (UnimplementedHandler) ActionMapfixRevoke(ctx context.Context, params Actio
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerRelease implements actionMapfixTriggerRelease operation.
|
||||
//
|
||||
// Role MapfixUpload changes status from Uploaded -> Releasing.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-release
|
||||
func (UnimplementedHandler) ActionMapfixTriggerRelease(ctx context.Context, params ActionMapfixTriggerReleaseParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerSubmit implements actionMapfixTriggerSubmit operation.
|
||||
//
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||
@@ -88,7 +97,7 @@ func (UnimplementedHandler) ActionMapfixTriggerSubmitUnchecked(ctx context.Conte
|
||||
|
||||
// ActionMapfixTriggerUpload implements actionMapfixTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
// Role MapfixUpload changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-upload
|
||||
func (UnimplementedHandler) ActionMapfixTriggerUpload(ctx context.Context, params ActionMapfixTriggerUploadParams) error {
|
||||
@@ -104,9 +113,18 @@ func (UnimplementedHandler) ActionMapfixTriggerValidate(ctx context.Context, par
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixUploaded implements actionMapfixUploaded operation.
|
||||
//
|
||||
// Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-releasing
|
||||
func (UnimplementedHandler) ActionMapfixUploaded(ctx context.Context, params ActionMapfixUploadedParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixValidated implements actionMapfixValidated operation.
|
||||
//
|
||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
// Role MapfixUpload manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-uploading
|
||||
func (UnimplementedHandler) ActionMapfixValidated(ctx context.Context, params ActionMapfixValidatedParams) error {
|
||||
@@ -188,7 +206,7 @@ func (UnimplementedHandler) ActionSubmissionTriggerSubmitUnchecked(ctx context.C
|
||||
|
||||
// ActionSubmissionTriggerUpload implements actionSubmissionTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
// Role SubmissionUpload changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/trigger-upload
|
||||
func (UnimplementedHandler) ActionSubmissionTriggerUpload(ctx context.Context, params ActionSubmissionTriggerUploadParams) error {
|
||||
@@ -206,7 +224,8 @@ func (UnimplementedHandler) ActionSubmissionTriggerValidate(ctx context.Context,
|
||||
|
||||
// ActionSubmissionValidated implements actionSubmissionValidated operation.
|
||||
//
|
||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
// Role SubmissionUpload manually resets uploading softlock and changes status from Uploading ->
|
||||
// Validated.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/reset-uploading
|
||||
func (UnimplementedHandler) ActionSubmissionValidated(ctx context.Context, params ActionSubmissionValidatedParams) error {
|
||||
@@ -420,9 +439,18 @@ func (UnimplementedHandler) ListSubmissions(ctx context.Context, params ListSubm
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// MigrateMapfixes implements migrateMapfixes operation.
|
||||
//
|
||||
// Perform the Uploaded -> Released migration.
|
||||
//
|
||||
// POST /mapfixes/migrate
|
||||
func (UnimplementedHandler) MigrateMapfixes(ctx context.Context) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ReleaseSubmissions implements releaseSubmissions operation.
|
||||
//
|
||||
// Release a set of uploaded maps.
|
||||
// Release a set of uploaded maps. Role SubmissionRelease.
|
||||
//
|
||||
// POST /release-submissions
|
||||
func (UnimplementedHandler) ReleaseSubmissions(ctx context.Context, req []ReleaseInfo) error {
|
||||
|
||||
@@ -390,6 +390,60 @@ func (s *Mapfix) Validate() error {
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if err := func() error {
|
||||
if value, ok := s.ValidatedAssetID.Get(); ok {
|
||||
if err := func() error {
|
||||
if err := (validate.Int{
|
||||
MinSet: true,
|
||||
Min: 0,
|
||||
MaxSet: false,
|
||||
Max: 0,
|
||||
MinExclusive: false,
|
||||
MaxExclusive: false,
|
||||
MultipleOfSet: false,
|
||||
MultipleOf: 0,
|
||||
}).Validate(int64(value)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "ValidatedAssetID",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if err := func() error {
|
||||
if value, ok := s.ValidatedAssetVersion.Get(); ok {
|
||||
if err := func() error {
|
||||
if err := (validate.Int{
|
||||
MinSet: true,
|
||||
Min: 0,
|
||||
MaxSet: false,
|
||||
Max: 0,
|
||||
MinExclusive: false,
|
||||
MaxExclusive: false,
|
||||
MultipleOfSet: false,
|
||||
MultipleOf: 0,
|
||||
}).Validate(int64(value)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "ValidatedAssetVersion",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if err := func() error {
|
||||
if err := (validate.Int{
|
||||
MinSet: true,
|
||||
|
||||
@@ -61,6 +61,7 @@ type Mapfixes interface {
|
||||
Delete(ctx context.Context, id int64) error
|
||||
List(ctx context.Context, filters OptionalMap, page model.Page, sort ListSort) ([]model.Mapfix, error)
|
||||
ListWithTotal(ctx context.Context, filters OptionalMap, page model.Page, sort ListSort) (int64, []model.Mapfix, error)
|
||||
Migrate(ctx context.Context) error
|
||||
}
|
||||
|
||||
type Operations interface {
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type Mapfixes struct {
|
||||
@@ -151,3 +153,18 @@ func (env *Mapfixes) ListWithTotal(ctx context.Context, filters datastore.Option
|
||||
|
||||
return total, maps, nil
|
||||
}
|
||||
|
||||
func (env *Mapfixes) Migrate(ctx context.Context) error {
|
||||
migrate_from := model.MapfixStatusUploaded
|
||||
migrate_to := model.MapfixStatusReleased
|
||||
count := int64(0)
|
||||
err := env.db.
|
||||
Model(&model.Mapfix{}).
|
||||
Where("status_id = ?", migrate_from).
|
||||
Set("status_id = ?", migrate_to).
|
||||
Count(&count).
|
||||
Error
|
||||
|
||||
log.Println("Mapfixes Migration rows affected:",count)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -18,10 +18,12 @@ const (
|
||||
MapfixStatusValidating MapfixStatus = 5
|
||||
MapfixStatusValidated MapfixStatus = 6
|
||||
MapfixStatusUploading MapfixStatus = 7
|
||||
MapfixStatusUploaded MapfixStatus = 8 // uploaded to the group, but pending release
|
||||
MapfixStatusReleasing MapfixStatus = 11
|
||||
|
||||
// Phase: Final MapfixStatus
|
||||
MapfixStatusUploaded MapfixStatus = 8 // uploaded to the group, but pending release
|
||||
MapfixStatusRejected MapfixStatus = 9
|
||||
MapfixStatusReleased MapfixStatus = 10
|
||||
)
|
||||
|
||||
type Mapfix struct {
|
||||
|
||||
@@ -65,3 +65,29 @@ type UploadMapfixRequest struct {
|
||||
ModelVersion uint64
|
||||
TargetAssetID uint64
|
||||
}
|
||||
|
||||
type ReleaseSubmissionRequest struct {
|
||||
// Release schedule
|
||||
SubmissionID int64
|
||||
ReleaseDate int64
|
||||
// Model download info
|
||||
ModelID uint64
|
||||
ModelVersion uint64
|
||||
// MapCreate
|
||||
UploadedAssetID uint64
|
||||
DisplayName string
|
||||
Creator string
|
||||
GameID uint32
|
||||
Submitter uint64
|
||||
}
|
||||
type BatchReleaseSubmissionsRequest struct {
|
||||
Submissions []ReleaseSubmissionRequest
|
||||
OperationID int32
|
||||
}
|
||||
|
||||
type ReleaseMapfixRequest struct {
|
||||
MapfixID int64
|
||||
ModelID uint64
|
||||
ModelVersion uint64
|
||||
TargetAssetID uint64
|
||||
}
|
||||
|
||||
@@ -114,3 +114,7 @@ func (svc *Service) UpdateMapfixIfStatus(ctx context.Context, id int64, statuses
|
||||
func (svc *Service) UpdateAndGetMapfixIfStatus(ctx context.Context, id int64, statuses []model.MapfixStatus, pmap MapfixUpdate) (model.Mapfix, error) {
|
||||
return svc.db.Mapfixes().IfStatusThenUpdateAndGet(ctx, id, statuses, datastore.OptionalMap(pmap))
|
||||
}
|
||||
|
||||
func (svc *Service) MigrateMapfixes(ctx context.Context) error {
|
||||
return svc.db.Mapfixes().Migrate(ctx)
|
||||
}
|
||||
|
||||
@@ -112,3 +112,29 @@ func (svc *Service) NatsValidateMapfix(
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) NatsReleaseMapfix(
|
||||
MapfixID int64,
|
||||
ModelID uint64,
|
||||
ModelVersion uint64,
|
||||
TargetAssetID uint64,
|
||||
) error {
|
||||
release_fix_request := model.ReleaseMapfixRequest{
|
||||
MapfixID: MapfixID,
|
||||
ModelID: ModelID,
|
||||
ModelVersion: ModelVersion,
|
||||
TargetAssetID: TargetAssetID,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(release_fix_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.nats.Publish("maptest.mapfixes.release", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -88,6 +88,28 @@ func (svc *Service) NatsUploadSubmission(
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) NatsBatchReleaseSubmissions(
|
||||
Submissions []model.ReleaseSubmissionRequest,
|
||||
operation int32,
|
||||
) error {
|
||||
release_new_request := model.BatchReleaseSubmissionsRequest{
|
||||
Submissions: Submissions,
|
||||
OperationID: operation,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(release_new_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.nats.Publish("maptest.submissions.batchrelease", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) NatsValidateSubmission(
|
||||
SubmissionID int64,
|
||||
ModelID uint64,
|
||||
|
||||
@@ -26,6 +26,8 @@ func NewMapfixesController(
|
||||
var(
|
||||
// prevent two mapfixes with same asset id
|
||||
ActiveMapfixStatuses = []model.MapfixStatus{
|
||||
model.MapfixStatusReleasing,
|
||||
model.MapfixStatusUploaded,
|
||||
model.MapfixStatusUploading,
|
||||
model.MapfixStatusValidated,
|
||||
model.MapfixStatusValidating,
|
||||
@@ -184,7 +186,7 @@ func (svc *Mapfixes) SetStatusValidated(ctx context.Context, params *validator.M
|
||||
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-failed
|
||||
func (svc *Mapfixes) SetStatusFailed(ctx context.Context, params *validator.MapfixID) (*validator.NullResponse, error) {
|
||||
func (svc *Mapfixes) SetStatusNotValidated(ctx context.Context, params *validator.MapfixID) (*validator.NullResponse, error) {
|
||||
MapfixID := int64(params.ID)
|
||||
// transaction
|
||||
target_status := model.MapfixStatusAcceptedUnvalidated
|
||||
@@ -253,6 +255,117 @@ func (svc *Mapfixes) SetStatusUploaded(ctx context.Context, params *validator.Ma
|
||||
|
||||
return &validator.NullResponse{}, nil
|
||||
}
|
||||
func (svc *Mapfixes) SetStatusNotUploaded(ctx context.Context, params *validator.MapfixID) (*validator.NullResponse, error) {
|
||||
MapfixID := int64(params.ID)
|
||||
// transaction
|
||||
target_status := model.MapfixStatusValidated
|
||||
update := service.NewMapfixUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
allow_statuses := []model.MapfixStatus{model.MapfixStatusUploading}
|
||||
err := svc.inner.UpdateMapfixIfStatus(ctx, MapfixID, allow_statuses, update)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// push an action audit event
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
err = svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
model.ValidatorUserID,
|
||||
model.Resource{
|
||||
ID: MapfixID,
|
||||
Type: model.ResourceMapfix,
|
||||
},
|
||||
event_data,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &validator.NullResponse{}, nil
|
||||
}
|
||||
|
||||
// ActionMapfixReleased implements actionMapfixReleased operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Releasing -> Released.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-released
|
||||
func (svc *Mapfixes) SetStatusReleased(ctx context.Context, params *validator.MapfixReleaseRequest) (*validator.NullResponse, error) {
|
||||
MapfixID := int64(params.MapfixID)
|
||||
// transaction
|
||||
target_status := model.MapfixStatusReleased
|
||||
update := service.NewMapfixUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
allow_statuses := []model.MapfixStatus{model.MapfixStatusReleasing}
|
||||
err := svc.inner.UpdateMapfixIfStatus(ctx, MapfixID, allow_statuses, update)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
err = svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
model.ValidatorUserID,
|
||||
model.Resource{
|
||||
ID: MapfixID,
|
||||
Type: model.ResourceMapfix,
|
||||
},
|
||||
event_data,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// metadata maintenance
|
||||
map_update := service.NewMapUpdate()
|
||||
map_update.SetAssetVersion(params.AssetVersion)
|
||||
map_update.SetModes(params.Modes)
|
||||
|
||||
err = svc.inner.UpdateMap(ctx, int64(params.TargetAssetID), map_update)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &validator.NullResponse{}, nil
|
||||
}
|
||||
func (svc *Mapfixes) SetStatusNotReleased(ctx context.Context, params *validator.MapfixID) (*validator.NullResponse, error) {
|
||||
MapfixID := int64(params.ID)
|
||||
// transaction
|
||||
target_status := model.MapfixStatusUploaded
|
||||
update := service.NewMapfixUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
allow_statuses := []model.MapfixStatus{model.MapfixStatusReleasing}
|
||||
err := svc.inner.UpdateMapfixIfStatus(ctx, MapfixID, allow_statuses, update)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// push an action audit event
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
err = svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
model.ValidatorUserID,
|
||||
model.Resource{
|
||||
ID: MapfixID,
|
||||
Type: model.ResourceMapfix,
|
||||
},
|
||||
event_data,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &validator.NullResponse{}, nil
|
||||
}
|
||||
|
||||
// CreateMapfixAuditError implements createMapfixAuditError operation.
|
||||
//
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.itzana.me/strafesnet/go-grpc/validator"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
@@ -24,7 +25,7 @@ func NewSubmissionsController(
|
||||
}
|
||||
|
||||
var(
|
||||
// prevent two mapfixes with same asset id
|
||||
// prevent two submissions with same asset id
|
||||
ActiveSubmissionStatuses = []model.SubmissionStatus{
|
||||
model.SubmissionStatusUploading,
|
||||
model.SubmissionStatusValidated,
|
||||
@@ -202,7 +203,7 @@ func (svc *Submissions) SetStatusValidated(ctx context.Context, params *validato
|
||||
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/validator-failed
|
||||
func (svc *Submissions) SetStatusFailed(ctx context.Context, params *validator.SubmissionID) (*validator.NullResponse, error) {
|
||||
func (svc *Submissions) SetStatusNotValidated(ctx context.Context, params *validator.SubmissionID) (*validator.NullResponse, error) {
|
||||
SubmissionID := int64(params.ID)
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusAcceptedUnvalidated
|
||||
@@ -273,6 +274,68 @@ func (svc *Submissions) SetStatusUploaded(ctx context.Context, params *validator
|
||||
return &validator.NullResponse{}, nil
|
||||
}
|
||||
|
||||
func (svc *Submissions) SetStatusNotUploaded(ctx context.Context, params *validator.SubmissionID) (*validator.NullResponse, error) {
|
||||
SubmissionID := int64(params.ID)
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusValidated
|
||||
update := service.NewSubmissionUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
allowed_statuses :=[]model.SubmissionStatus{model.SubmissionStatusUploading}
|
||||
err := svc.inner.UpdateSubmissionIfStatus(ctx, SubmissionID, allowed_statuses, update)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// push an action audit event
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
err = svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
model.ValidatorUserID,
|
||||
model.Resource{
|
||||
ID: SubmissionID,
|
||||
Type: model.ResourceSubmission,
|
||||
},
|
||||
event_data,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &validator.NullResponse{}, nil
|
||||
}
|
||||
|
||||
func (svc *Submissions) SetStatusReleased(ctx context.Context, params *validator.SubmissionReleaseRequest) (*validator.NullResponse, error){
|
||||
// create map with go-grpc
|
||||
_, err := svc.inner.CreateMap(ctx, model.Map{
|
||||
ID: params.MapCreate.ID,
|
||||
DisplayName: params.MapCreate.DisplayName,
|
||||
Creator: params.MapCreate.Creator,
|
||||
GameID: params.MapCreate.GameID,
|
||||
Date: time.Unix(params.MapCreate.Date, 0),
|
||||
Submitter: params.MapCreate.Submitter,
|
||||
Thumbnail: 0,
|
||||
AssetVersion: params.MapCreate.AssetVersion,
|
||||
LoadCount: 0,
|
||||
Modes: params.MapCreate.Modes,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// update status to Released
|
||||
update := service.NewSubmissionUpdate()
|
||||
update.SetStatusID(model.SubmissionStatusReleased)
|
||||
err = svc.inner.UpdateSubmissionIfStatus(ctx, int64(params.SubmissionID), []model.SubmissionStatus{model.SubmissionStatusUploaded}, update)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &validator.NullResponse{}, nil
|
||||
}
|
||||
|
||||
// CreateSubmissionAuditError implements createSubmissionAuditError operation.
|
||||
//
|
||||
// Post an error to the audit log
|
||||
|
||||
@@ -22,6 +22,8 @@ var(
|
||||
}
|
||||
// limit mapfixes in the pipeline to one per target map
|
||||
ActiveAcceptedMapfixStatuses = []model.MapfixStatus{
|
||||
model.MapfixStatusReleasing,
|
||||
model.MapfixStatusUploaded,
|
||||
model.MapfixStatusUploading,
|
||||
model.MapfixStatusValidated,
|
||||
model.MapfixStatusValidating,
|
||||
@@ -193,6 +195,9 @@ func (svc *Service) ListMapfixes(ctx context.Context, params api.ListMapfixesPar
|
||||
if asset_id, asset_id_ok := params.AssetID.Get(); asset_id_ok{
|
||||
filter.SetAssetID(uint64(asset_id))
|
||||
}
|
||||
if asset_version, asset_version_ok := params.AssetVersion.Get(); asset_version_ok{
|
||||
filter.SetAssetVersion(uint64(asset_version))
|
||||
}
|
||||
if target_asset_id, target_asset_id_ok := params.TargetAssetID.Get(); target_asset_id_ok{
|
||||
filter.SetTargetAssetID(uint64(target_asset_id))
|
||||
}
|
||||
@@ -786,6 +791,127 @@ func (svc *Service) ActionMapfixValidated(ctx context.Context, params api.Action
|
||||
)
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerRelease invokes actionMapfixTriggerRelease operation.
|
||||
//
|
||||
// Role MapfixUpload changes status from Uploaded -> Releasing.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-release
|
||||
func (svc *Service) ActionMapfixTriggerRelease(ctx context.Context, params api.ActionMapfixTriggerReleaseParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleMapfixUpload()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapfixUpload
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.MapfixStatusReleasing
|
||||
update := service.NewMapfixUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
allow_statuses := []model.MapfixStatus{model.MapfixStatusUploaded}
|
||||
mapfix, err := svc.inner.UpdateAndGetMapfixIfStatus(ctx, params.MapfixID, allow_statuses, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// this is a map fix
|
||||
err = svc.inner.NatsReleaseMapfix(
|
||||
mapfix.ID,
|
||||
mapfix.ValidatedAssetID,
|
||||
mapfix.ValidatedAssetVersion,
|
||||
mapfix.TargetAssetID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
return svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
userId,
|
||||
model.Resource{
|
||||
ID: params.MapfixID,
|
||||
Type: model.ResourceMapfix,
|
||||
},
|
||||
event_data,
|
||||
)
|
||||
}
|
||||
|
||||
// ActionMapfixUploaded invokes actionMapfixUploaded operation.
|
||||
//
|
||||
// Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-releasing
|
||||
func (svc *Service) ActionMapfixUploaded(ctx context.Context, params api.ActionMapfixUploadedParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleMapfixUpload()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapfixUpload
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check when mapfix was updated
|
||||
mapfix, err := svc.inner.GetMapfix(ctx, params.MapfixID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if time.Now().Before(mapfix.UpdatedAt.Add(time.Second*10)) {
|
||||
// the last time the mapfix was updated must be longer than 10 seconds ago
|
||||
return ErrDelayReset
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.MapfixStatusUploaded
|
||||
update := service.NewMapfixUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
allow_statuses := []model.MapfixStatus{model.MapfixStatusReleasing}
|
||||
err = svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, allow_statuses, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
return svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
userId,
|
||||
model.Resource{
|
||||
ID: params.MapfixID,
|
||||
Type: model.ResourceMapfix,
|
||||
},
|
||||
event_data,
|
||||
)
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerValidate invokes actionMapfixTriggerValidate operation.
|
||||
//
|
||||
// Role Reviewer triggers validation and changes status from Submitted -> Validating.
|
||||
@@ -1066,3 +1192,26 @@ func (svc *Service) ListMapfixAuditEvents(ctx context.Context, params api.ListMa
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// MigrateMapfixes invokes MigrateMapfixes operation.
|
||||
//
|
||||
// Retrieve a list of audit events.
|
||||
//
|
||||
// GET /mapfixes/{MapfixID}/audit-events
|
||||
func (svc *Service) MigrateMapfixes(ctx context.Context) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleSubmissionRelease()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleSubmissionRelease
|
||||
}
|
||||
|
||||
return svc.inner.MigrateMapfixes(ctx)
|
||||
}
|
||||
|
||||
@@ -20,13 +20,6 @@ var(
|
||||
model.SubmissionStatusSubmitted,
|
||||
model.SubmissionStatusUnderConstruction,
|
||||
}
|
||||
// limit submissions in the pipeline to one per target map
|
||||
ActiveAcceptedSubmissionStatuses = []model.SubmissionStatus{
|
||||
model.SubmissionStatusUploading,
|
||||
model.SubmissionStatusValidated,
|
||||
model.SubmissionStatusValidating,
|
||||
model.SubmissionStatusAcceptedUnvalidated,
|
||||
}
|
||||
// Allow 5 submissions every 10 minutes
|
||||
CreateSubmissionRateLimit int64 = 5
|
||||
CreateSubmissionRecencyWindow = time.Second*600
|
||||
@@ -236,6 +229,9 @@ func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissi
|
||||
if asset_id, asset_id_ok := params.AssetID.Get(); asset_id_ok{
|
||||
filter.SetAssetID(uint64(asset_id))
|
||||
}
|
||||
if asset_version, asset_version_ok := params.AssetVersion.Get(); asset_version_ok{
|
||||
filter.SetAssetVersion(uint64(asset_version))
|
||||
}
|
||||
if uploaded_asset_id, uploaded_asset_id_ok := params.UploadedAssetID.Get(); uploaded_asset_id_ok{
|
||||
filter.SetUploadedAssetID(uint64(uploaded_asset_id))
|
||||
}
|
||||
@@ -1053,6 +1049,11 @@ func (svc *Service) ReleaseSubmissions(ctx context.Context, request []api.Releas
|
||||
return ErrPermissionDeniedNeedRoleSubmissionRelease
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
idList := make([]int64, len(request))
|
||||
for i, releaseInfo := range request {
|
||||
idList[i] = releaseInfo.SubmissionID
|
||||
@@ -1074,32 +1075,39 @@ func (svc *Service) ReleaseSubmissions(ctx context.Context, request []api.Releas
|
||||
}
|
||||
}
|
||||
|
||||
for i,submission := range submissions{
|
||||
date := request[i].Date.Unix()
|
||||
// create each map with go-grpc
|
||||
_, err := svc.inner.CreateMap(ctx, model.Map{
|
||||
ID: int64(submission.UploadedAssetID),
|
||||
DisplayName: submission.DisplayName,
|
||||
Creator: submission.Creator,
|
||||
GameID: submission.GameID,
|
||||
Date: time.Unix(date, 0),
|
||||
Submitter: submission.Submitter,
|
||||
// Thumbnail: 0,
|
||||
// AssetVersion: 0,
|
||||
// LoadCount: 0,
|
||||
// Modes: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// construct batch release nats message
|
||||
release_submissions := make([]model.ReleaseSubmissionRequest, len(request))
|
||||
for i, submission := range submissions {
|
||||
// from request
|
||||
release_submissions[i].ReleaseDate = request[i].Date.Unix()
|
||||
release_submissions[i].SubmissionID = request[i].SubmissionID
|
||||
// from submission
|
||||
release_submissions[i].ModelID = submission.ValidatedAssetID
|
||||
release_submissions[i].ModelVersion = submission.ValidatedAssetVersion
|
||||
// for map create
|
||||
release_submissions[i].UploadedAssetID = submission.UploadedAssetID
|
||||
release_submissions[i].DisplayName = submission.DisplayName
|
||||
release_submissions[i].Creator = submission.Creator
|
||||
release_submissions[i].GameID = submission.GameID
|
||||
release_submissions[i].Submitter = submission.Submitter
|
||||
}
|
||||
|
||||
// update each status to Released
|
||||
update := service.NewSubmissionUpdate()
|
||||
update.SetStatusID(model.SubmissionStatusReleased)
|
||||
err = svc.inner.UpdateSubmissionIfStatus(ctx, submission.ID, []model.SubmissionStatus{model.SubmissionStatusUploaded}, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// create a trackable long-running operation
|
||||
operation, err := svc.inner.CreateOperation(ctx, model.Operation{
|
||||
Owner: userId,
|
||||
StatusID: model.OperationStatusCreated,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// this is a map fix
|
||||
err = svc.inner.NatsBatchReleaseSubmissions(
|
||||
release_submissions,
|
||||
operation.ID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "submissions-api"
|
||||
version = "0.8.2"
|
||||
version = "0.9.1"
|
||||
edition = "2024"
|
||||
publish = ["strafesnet"]
|
||||
repository = "https://git.itzana.me/StrafesNET/maps-service"
|
||||
|
||||
@@ -152,6 +152,48 @@ impl Context{
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub async fn get_mapfixes(&self,config:GetMapfixesRequest<'_>)->Result<MapfixesResponse,Error>{
|
||||
let url_raw=format!("{}/mapfixes",self.0.base_url);
|
||||
let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||
|
||||
{
|
||||
let mut query_pairs=url.query_pairs_mut();
|
||||
query_pairs.append_pair("Page",config.Page.to_string().as_str());
|
||||
query_pairs.append_pair("Limit",config.Limit.to_string().as_str());
|
||||
if let Some(sort)=config.Sort{
|
||||
query_pairs.append_pair("Sort",(sort as u8).to_string().as_str());
|
||||
}
|
||||
if let Some(display_name)=config.DisplayName{
|
||||
query_pairs.append_pair("DisplayName",display_name);
|
||||
}
|
||||
if let Some(creator)=config.Creator{
|
||||
query_pairs.append_pair("Creator",creator);
|
||||
}
|
||||
if let Some(game_id)=config.GameID{
|
||||
query_pairs.append_pair("GameID",(game_id as u8).to_string().as_str());
|
||||
}
|
||||
if let Some(submitter)=config.Submitter{
|
||||
query_pairs.append_pair("Submitter",submitter.to_string().as_str());
|
||||
}
|
||||
if let Some(asset_id)=config.AssetID{
|
||||
query_pairs.append_pair("AssetID",asset_id.to_string().as_str());
|
||||
}
|
||||
if let Some(asset_version)=config.AssetVersion{
|
||||
query_pairs.append_pair("AssetVersion",asset_version.to_string().as_str());
|
||||
}
|
||||
if let Some(uploaded_asset_id)=config.TargetAssetID{
|
||||
query_pairs.append_pair("TargetAssetID",uploaded_asset_id.to_string().as_str());
|
||||
}
|
||||
if let Some(status_id)=config.StatusID{
|
||||
query_pairs.append_pair("StatusID",(status_id as u8).to_string().as_str());
|
||||
}
|
||||
}
|
||||
|
||||
response_ok(
|
||||
self.0.get(url).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
pub async fn get_submissions(&self,config:GetSubmissionsRequest<'_>)->Result<SubmissionsResponse,Error>{
|
||||
let url_raw=format!("{}/submissions",self.0.base_url);
|
||||
let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||
@@ -178,6 +220,9 @@ impl Context{
|
||||
if let Some(asset_id)=config.AssetID{
|
||||
query_pairs.append_pair("AssetID",asset_id.to_string().as_str());
|
||||
}
|
||||
if let Some(asset_version)=config.AssetVersion{
|
||||
query_pairs.append_pair("AssetVersion",asset_version.to_string().as_str());
|
||||
}
|
||||
if let Some(uploaded_asset_id)=config.UploadedAssetID{
|
||||
query_pairs.append_pair("UploadedAssetID",uploaded_asset_id.to_string().as_str());
|
||||
}
|
||||
|
||||
@@ -252,6 +252,73 @@ pub enum Sort{
|
||||
DateDescending=4,
|
||||
}
|
||||
|
||||
#[derive(Clone,Debug,serde_repr::Serialize_repr,serde_repr::Deserialize_repr)]
|
||||
#[repr(u8)]
|
||||
pub enum MapfixStatus{
|
||||
// Phase: Creation
|
||||
UnderConstruction=0,
|
||||
ChangesRequested=1,
|
||||
|
||||
// Phase: Review
|
||||
Submitting=2,
|
||||
Submitted=3,
|
||||
|
||||
// Phase: Testing
|
||||
AcceptedUnvalidated=4, // pending script review, can re-trigger validation
|
||||
Validating=5,
|
||||
Validated=6,
|
||||
Uploading=7,
|
||||
Uploaded=8, // uploaded to the group, but pending release
|
||||
Releasing=11,
|
||||
|
||||
// Phase: Final MapfixStatus
|
||||
Rejected=9,
|
||||
Released=10,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct GetMapfixesRequest<'a>{
|
||||
pub Page:u32,
|
||||
pub Limit:u32,
|
||||
pub Sort:Option<Sort>,
|
||||
pub DisplayName:Option<&'a str>,
|
||||
pub Creator:Option<&'a str>,
|
||||
pub GameID:Option<GameID>,
|
||||
pub Submitter:Option<u64>,
|
||||
pub AssetID:Option<u64>,
|
||||
pub AssetVersion:Option<u64>,
|
||||
pub TargetAssetID:Option<u64>,
|
||||
pub StatusID:Option<MapfixStatus>,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug,serde::Serialize,serde::Deserialize)]
|
||||
pub struct MapfixResponse{
|
||||
pub ID:MapfixID,
|
||||
pub DisplayName:String,
|
||||
pub Creator:String,
|
||||
pub GameID:u32,
|
||||
pub CreatedAt:i64,
|
||||
pub UpdatedAt:i64,
|
||||
pub Submitter:u64,
|
||||
pub AssetID:u64,
|
||||
pub AssetVersion:u64,
|
||||
pub ValidatedAssetID:Option<u64>,
|
||||
pub ValidatedAssetVersion:Option<u64>,
|
||||
pub Completed:bool,
|
||||
pub TargetAssetID:u64,
|
||||
pub StatusID:MapfixStatus,
|
||||
pub Description:String,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug,serde::Deserialize)]
|
||||
pub struct MapfixesResponse{
|
||||
pub Total:u64,
|
||||
pub Mapfixes:Vec<MapfixResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone,Debug,serde_repr::Deserialize_repr)]
|
||||
#[repr(u8)]
|
||||
pub enum SubmissionStatus{
|
||||
@@ -286,6 +353,7 @@ pub struct GetSubmissionsRequest<'a>{
|
||||
pub GameID:Option<GameID>,
|
||||
pub Submitter:Option<u64>,
|
||||
pub AssetID:Option<u64>,
|
||||
pub AssetVersion:Option<u64>,
|
||||
pub UploadedAssetID:Option<u64>,
|
||||
pub StatusID:Option<SubmissionStatus>,
|
||||
}
|
||||
@@ -302,6 +370,8 @@ pub struct SubmissionResponse{
|
||||
pub Submitter:u64,
|
||||
pub AssetID:u64,
|
||||
pub AssetVersion:u64,
|
||||
pub ValidatedAssetID:Option<u64>,
|
||||
pub ValidatedAssetVersion:Option<u64>,
|
||||
pub UploadedAssetID:u64,
|
||||
pub StatusID:SubmissionStatus,
|
||||
}
|
||||
|
||||
@@ -17,5 +17,5 @@ siphasher = "1.0.1"
|
||||
tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread", "signal"] }
|
||||
heck = "0.5.0"
|
||||
lazy-regex = "3.4.1"
|
||||
rust-grpc = { version = "1.2.1", registry = "strafesnet" }
|
||||
tonic = "0.13.1"
|
||||
rust-grpc = { version = "1.6.1", registry = "strafesnet" }
|
||||
tonic = "0.14.1"
|
||||
|
||||
@@ -18,6 +18,9 @@ impl Service{
|
||||
endpoint!(set_status_submitted,SubmittedRequest,NullResponse);
|
||||
endpoint!(set_status_request_changes,MapfixId,NullResponse);
|
||||
endpoint!(set_status_validated,MapfixId,NullResponse);
|
||||
endpoint!(set_status_failed,MapfixId,NullResponse);
|
||||
endpoint!(set_status_not_validated,MapfixId,NullResponse);
|
||||
endpoint!(set_status_uploaded,MapfixId,NullResponse);
|
||||
endpoint!(set_status_not_uploaded,MapfixId,NullResponse);
|
||||
endpoint!(set_status_released,MapfixReleaseRequest,NullResponse);
|
||||
endpoint!(set_status_not_released,MapfixId,NullResponse);
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
use crate::endpoint;
|
||||
use rust_grpc::maps_extended::*;
|
||||
pub type ServiceClient=rust_grpc::maps_extended::maps_service_client::MapsServiceClient<tonic::transport::channel::Channel>;
|
||||
#[derive(Clone)]
|
||||
pub struct Client{
|
||||
client:ServiceClient,
|
||||
}
|
||||
impl Client{
|
||||
pub fn new(
|
||||
client:ServiceClient,
|
||||
)->Self{
|
||||
Self{client}
|
||||
}
|
||||
// endpoint!(get,MapId,MapResponse);
|
||||
// endpoint!(get_list,MapIdList,MapList);
|
||||
endpoint!(update,MapUpdate,NullResponse);
|
||||
// endpoint!(create,MapCreate,MapId);
|
||||
// endpoint!(delete,MapId,NullResponse);
|
||||
// endpoint!(list,ListRequest,MapList);
|
||||
// endpoint!(increment_load_count,MapId,NullResponse);
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
pub mod error;
|
||||
|
||||
pub mod maps_extended;
|
||||
pub mod mapfixes;
|
||||
pub mod operations;
|
||||
pub mod scripts;
|
||||
|
||||
@@ -11,5 +11,6 @@ impl Service{
|
||||
)->Self{
|
||||
Self{client}
|
||||
}
|
||||
endpoint!(success,OperationSuccessRequest,NullResponse);
|
||||
endpoint!(fail,OperationFailRequest,NullResponse);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ impl Service{
|
||||
endpoint!(set_status_submitted,SubmittedRequest,NullResponse);
|
||||
endpoint!(set_status_request_changes,SubmissionId,NullResponse);
|
||||
endpoint!(set_status_validated,SubmissionId,NullResponse);
|
||||
endpoint!(set_status_failed,SubmissionId,NullResponse);
|
||||
endpoint!(set_status_not_validated,SubmissionId,NullResponse);
|
||||
endpoint!(set_status_uploaded,StatusUploadedRequest,NullResponse);
|
||||
endpoint!(set_status_not_uploaded,SubmissionId,NullResponse);
|
||||
endpoint!(set_status_released,SubmissionReleaseRequest,NullResponse);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ mod check_submission;
|
||||
mod create;
|
||||
mod create_mapfix;
|
||||
mod create_submission;
|
||||
mod release;
|
||||
mod release_mapfix;
|
||||
mod release_submissions_batch;
|
||||
mod upload_mapfix;
|
||||
mod upload_submission;
|
||||
mod validator;
|
||||
@@ -53,9 +56,12 @@ async fn main()->Result<(),StartupError>{
|
||||
// create / upload models through STRAFESNET_CI2 account
|
||||
let cookie=std::env::var("RBXCOOKIE").expect("RBXCOOKIE env required");
|
||||
let cookie_context=rbx_asset::cookie::Context::new(rbx_asset::cookie::Cookie::new(cookie));
|
||||
// download models through cloud api
|
||||
// download models through cloud api (STRAFESNET_CI2 account)
|
||||
let api_key=std::env::var("RBX_API_KEY").expect("RBX_API_KEY env required");
|
||||
let cloud_context=rbx_asset::cloud::Context::new(rbx_asset::cloud::ApiKey::new(api_key));
|
||||
// luau execution cloud api (StrafesNET group)
|
||||
let api_key=std::env::var("RBX_API_KEY_LUAU_EXECUTION").expect("RBX_API_KEY_LUAU_EXECUTION env required");
|
||||
let cloud_context_luau_execution=rbx_asset::cloud::Context::new(rbx_asset::cloud::ApiKey::new(api_key));
|
||||
|
||||
// maps-service api
|
||||
let api_host_internal=std::env::var("API_HOST_INTERNAL").expect("API_HOST_INTERNAL env required");
|
||||
@@ -66,14 +72,16 @@ async fn main()->Result<(),StartupError>{
|
||||
let scripts=crate::grpc::scripts::Service::new(crate::grpc::scripts::ValidatorScriptsServiceClient::new(channel.clone()));
|
||||
let script_policy=crate::grpc::script_policy::Service::new(crate::grpc::script_policy::ValidatorScriptPolicyServiceClient::new(channel.clone()));
|
||||
let submissions=crate::grpc::submissions::Service::new(crate::grpc::submissions::ValidatorSubmissionsServiceClient::new(channel.clone()));
|
||||
let maps_extended=crate::grpc::maps_extended::Client::new(crate::grpc::maps_extended::ServiceClient::new(channel));
|
||||
let load_asset_version_runtime=rbx_asset::cloud::LuauSessionLatestRequest{
|
||||
place_id:load_asset_version_place_id,
|
||||
universe_id:load_asset_version_universe_id,
|
||||
};
|
||||
let message_handler=message_handler::MessageHandler{
|
||||
cloud_context,
|
||||
cookie_context,
|
||||
cloud_context_luau_execution,
|
||||
group_id,
|
||||
load_asset_version_place_id,
|
||||
load_asset_version_universe_id,
|
||||
maps_extended,
|
||||
load_asset_version_runtime,
|
||||
mapfixes,
|
||||
operations,
|
||||
scripts,
|
||||
|
||||
@@ -9,6 +9,8 @@ pub enum HandleMessageError{
|
||||
CreateSubmission(tonic::Status),
|
||||
CheckMapfix(crate::check_mapfix::Error),
|
||||
CheckSubmission(crate::check_submission::Error),
|
||||
ReleaseMapfix(crate::release_mapfix::Error),
|
||||
ReleaseSubmissionsBatch(crate::release_submissions_batch::Error),
|
||||
UploadMapfix(crate::upload_mapfix::Error),
|
||||
UploadSubmission(crate::upload_submission::Error),
|
||||
ValidateMapfix(crate::validate_mapfix::Error),
|
||||
@@ -30,10 +32,9 @@ fn from_slice<'a,T:serde::de::Deserialize<'a>>(slice:&'a [u8])->Result<T,HandleM
|
||||
pub struct MessageHandler{
|
||||
pub(crate) cloud_context:rbx_asset::cloud::Context,
|
||||
pub(crate) cookie_context:rbx_asset::cookie::Context,
|
||||
pub(crate) cloud_context_luau_execution:rbx_asset::cloud::Context,
|
||||
pub(crate) group_id:Option<u64>,
|
||||
pub(crate) load_asset_version_place_id:u64,
|
||||
pub(crate) load_asset_version_universe_id:u64,
|
||||
pub(crate) maps_extended:crate::grpc::maps_extended::Client,
|
||||
pub(crate) load_asset_version_runtime:rbx_asset::cloud::LuauSessionLatestRequest,
|
||||
pub(crate) mapfixes:crate::grpc::mapfixes::Service,
|
||||
pub(crate) operations:crate::grpc::operations::Service,
|
||||
pub(crate) scripts:crate::grpc::scripts::Service,
|
||||
@@ -50,6 +51,8 @@ impl MessageHandler{
|
||||
"maptest.submissions.create"=>self.create_submission(from_slice(&message.payload)?).await.map_err(HandleMessageError::CreateSubmission),
|
||||
"maptest.mapfixes.check"=>self.check_mapfix(from_slice(&message.payload)?).await.map_err(HandleMessageError::CheckMapfix),
|
||||
"maptest.submissions.check"=>self.check_submission(from_slice(&message.payload)?).await.map_err(HandleMessageError::CheckSubmission),
|
||||
"maptest.mapfixes.release"=>self.release_mapfix(from_slice(&message.payload)?).await.map_err(HandleMessageError::ReleaseMapfix),
|
||||
"maptest.submissions.batchrelease"=>self.release_submissions_batch(from_slice(&message.payload)?).await.map_err(HandleMessageError::ReleaseSubmissionsBatch),
|
||||
"maptest.mapfixes.upload"=>self.upload_mapfix(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadMapfix),
|
||||
"maptest.submissions.upload"=>self.upload_submission(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadSubmission),
|
||||
"maptest.mapfixes.validate"=>self.validate_mapfix(from_slice(&message.payload)?).await.map_err(HandleMessageError::ValidateMapfix),
|
||||
|
||||
@@ -81,3 +81,34 @@ pub struct UploadMapfixRequest{
|
||||
pub ModelVersion:u64,
|
||||
pub TargetAssetID:u64,
|
||||
}
|
||||
|
||||
// Release a new map
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct ReleaseSubmissionRequest{
|
||||
pub SubmissionID:u64,
|
||||
pub ReleaseDate:i64,
|
||||
pub ModelID:u64,
|
||||
pub ModelVersion:u64,
|
||||
pub UploadedAssetID:u64,
|
||||
pub DisplayName:String,
|
||||
pub Creator:String,
|
||||
pub GameID:u32,
|
||||
pub Submitter:u64,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct ReleaseSubmissionsBatchRequest{
|
||||
pub Submissions:Vec<ReleaseSubmissionRequest>,
|
||||
pub OperationID:u32,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct ReleaseMapfixRequest{
|
||||
pub MapfixID:u64,
|
||||
pub ModelID:u64,
|
||||
pub ModelVersion:u64,
|
||||
pub TargetAssetID:u64,
|
||||
}
|
||||
|
||||
104
validation/src/release.rs
Normal file
104
validation/src/release.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
use crate::rbx_util::read_dom;
|
||||
|
||||
#[expect(unused)]
|
||||
#[derive(Debug)]
|
||||
pub enum ModesError{
|
||||
ApiActionMapfixReleased(tonic::Status),
|
||||
ModelFileDecode(crate::rbx_util::ReadDomError),
|
||||
GetRootInstance(crate::rbx_util::GetRootInstanceError),
|
||||
NonSequentialModes,
|
||||
TooManyModes(usize),
|
||||
}
|
||||
impl std::fmt::Display for ModesError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for ModesError{}
|
||||
|
||||
// decode and get modes function
|
||||
pub fn count_modes(maybe_gzip:rbx_asset::types::MaybeGzippedBytes)->Result<u32,ModesError>{
|
||||
// decode dom (slow!)
|
||||
let dom=maybe_gzip.read_with(read_dom,read_dom).map_err(ModesError::ModelFileDecode)?;
|
||||
|
||||
// extract the root instance
|
||||
let model_instance=crate::rbx_util::get_root_instance(&dom).map_err(ModesError::GetRootInstance)?;
|
||||
|
||||
// extract information from the model
|
||||
let model_info=crate::check::get_model_info(&dom,model_instance);
|
||||
|
||||
// count modes
|
||||
let modes=model_info.count_modes().ok_or(ModesError::NonSequentialModes)?;
|
||||
|
||||
// hard limit LOL
|
||||
let modes=if modes<u32::MAX as usize{
|
||||
modes as u32
|
||||
}else{
|
||||
return Err(ModesError::TooManyModes(modes));
|
||||
};
|
||||
|
||||
Ok(modes)
|
||||
}
|
||||
|
||||
#[expect(unused)]
|
||||
#[derive(Debug)]
|
||||
pub enum LoadAssetVersionsError{
|
||||
CreateSession(rbx_asset::cloud::CreateError),
|
||||
NonPositiveNumber(serde_json::Value),
|
||||
Script(rbx_asset::cloud::LuauError),
|
||||
InvalidResult(Vec<serde_json::Value>),
|
||||
LuauSession(rbx_asset::cloud::LuauSessionError),
|
||||
}
|
||||
impl std::fmt::Display for LoadAssetVersionsError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for LoadAssetVersionsError{}
|
||||
|
||||
// get asset versions in bulk using Roblox Luau API
|
||||
pub async fn load_asset_versions<I:IntoIterator<Item=u64>>(
|
||||
context:&rbx_asset::cloud::Context,
|
||||
runtime:&rbx_asset::cloud::LuauSessionLatestRequest,
|
||||
assets:I,
|
||||
)->Result<Vec<u64>,LoadAssetVersionsError>{
|
||||
// construct script with inline IDs
|
||||
// TODO: concurrent execution
|
||||
let mut script="local InsertService=game:GetService(\"InsertService\")\n".to_string();
|
||||
script+="return {\n";
|
||||
for asset in assets{
|
||||
script+="InsertService:GetLatestAssetVersionAsync(";
|
||||
script+=&asset.to_string();
|
||||
script+="),\n";
|
||||
}
|
||||
script+="}\n";
|
||||
|
||||
let session=rbx_asset::cloud::LuauSessionCreate{
|
||||
script:&script,
|
||||
user:None,
|
||||
timeout:None,
|
||||
binaryInput:None,
|
||||
enableBinaryOutput:None,
|
||||
binaryOutputUri:None,
|
||||
};
|
||||
let session_response=context.create_luau_session(runtime,session).await.map_err(LoadAssetVersionsError::CreateSession)?;
|
||||
|
||||
let result=crate::rbx_util::get_luau_result_exp_backoff(&context,&session_response).await;
|
||||
|
||||
// * Note that only one mapfix can be active per map
|
||||
// * so it's theoretically impossible for the map to be updated unexpectedly.
|
||||
// * This means that the incremental asset version does not
|
||||
// * need to be checked before and after the load asset version is checked.
|
||||
|
||||
match result{
|
||||
Ok(Ok(rbx_asset::cloud::LuauResults{results}))=>{
|
||||
results.into_iter().map(|load_asset_version|
|
||||
load_asset_version.as_u64().ok_or_else(||LoadAssetVersionsError::NonPositiveNumber(load_asset_version.clone()))
|
||||
).collect()
|
||||
},
|
||||
Ok(Err(e))=>Err(LoadAssetVersionsError::Script(e)),
|
||||
Err(e)=>Err(LoadAssetVersionsError::LuauSession(e)),
|
||||
}
|
||||
|
||||
// * Don't need to check asset version to make sure it hasn't been updated
|
||||
}
|
||||
101
validation/src/release_mapfix.rs
Normal file
101
validation/src/release_mapfix.rs
Normal file
@@ -0,0 +1,101 @@
|
||||
use crate::download::download_asset_version;
|
||||
use crate::nats_types::ReleaseMapfixRequest;
|
||||
use crate::release::{count_modes,load_asset_versions};
|
||||
|
||||
#[expect(unused)]
|
||||
#[derive(Debug)]
|
||||
pub enum InnerError{
|
||||
Download(crate::download::Error),
|
||||
Modes(crate::release::ModesError),
|
||||
LoadAssetVersions(crate::release::LoadAssetVersionsError),
|
||||
LoadAssetVersionsListLength,
|
||||
}
|
||||
impl std::fmt::Display for InnerError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for InnerError{}
|
||||
|
||||
async fn release_inner(
|
||||
cloud_context:&rbx_asset::cloud::Context,
|
||||
cloud_context_luau_execution:&rbx_asset::cloud::Context,
|
||||
load_asset_version_runtime:&rbx_asset::cloud::LuauSessionLatestRequest,
|
||||
release_info:ReleaseMapfixRequest,
|
||||
)->Result<rust_grpc::validator::MapfixReleaseRequest,InnerError>{
|
||||
// download the map model
|
||||
let maybe_gzip=download_asset_version(cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
|
||||
asset_id:release_info.ModelID,
|
||||
version:release_info.ModelVersion,
|
||||
}).await.map_err(InnerError::Download)?;
|
||||
|
||||
// count modes
|
||||
let modes=count_modes(maybe_gzip).map_err(InnerError::Modes)?;
|
||||
|
||||
// fetch load asset version
|
||||
let load_asset_versions=load_asset_versions(
|
||||
cloud_context_luau_execution,
|
||||
load_asset_version_runtime,
|
||||
[release_info.TargetAssetID],
|
||||
).await.map_err(InnerError::LoadAssetVersions)?;
|
||||
|
||||
// exactly one value in the results
|
||||
let &[load_asset_version]=load_asset_versions.as_slice()else{
|
||||
return Err(InnerError::LoadAssetVersionsListLength);
|
||||
};
|
||||
|
||||
Ok(rust_grpc::validator::MapfixReleaseRequest{
|
||||
mapfix_id:release_info.MapfixID,
|
||||
target_asset_id:release_info.TargetAssetID,
|
||||
asset_version:load_asset_version,
|
||||
modes:modes,
|
||||
})
|
||||
}
|
||||
|
||||
#[expect(unused)]
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
ApiActionMapfixRelease(tonic::Status),
|
||||
}
|
||||
impl std::fmt::Display for Error{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for Error{}
|
||||
|
||||
impl crate::message_handler::MessageHandler{
|
||||
pub async fn release_mapfix(&self,release_info:ReleaseMapfixRequest)->Result<(),Error>{
|
||||
let mapfix_id=release_info.MapfixID;
|
||||
let result=release_inner(
|
||||
&self.cloud_context,
|
||||
&self.cloud_context_luau_execution,
|
||||
&self.load_asset_version_runtime,
|
||||
release_info,
|
||||
).await;
|
||||
|
||||
match result{
|
||||
Ok(request)=>{
|
||||
// update map metadata
|
||||
self.mapfixes.set_status_released(request).await.map_err(Error::ApiActionMapfixRelease)?;
|
||||
},
|
||||
Err(e)=>{
|
||||
// log error
|
||||
println!("[release_mapfix] Error: {e}");
|
||||
|
||||
// post an error message to the audit log
|
||||
self.mapfixes.create_audit_error(rust_grpc::validator::AuditErrorRequest{
|
||||
id:mapfix_id,
|
||||
error_message:e.to_string(),
|
||||
}).await.map_err(Error::ApiActionMapfixRelease)?;
|
||||
|
||||
// update the mapfix model status to uploaded
|
||||
self.mapfixes.set_status_not_released(rust_grpc::validator::MapfixId{
|
||||
id:mapfix_id,
|
||||
}).await.map_err(Error::ApiActionMapfixRelease)?;
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
227
validation/src/release_submissions_batch.rs
Normal file
227
validation/src/release_submissions_batch.rs
Normal file
@@ -0,0 +1,227 @@
|
||||
use futures::StreamExt;
|
||||
|
||||
use crate::download::download_asset_version;
|
||||
use crate::nats_types::ReleaseSubmissionsBatchRequest;
|
||||
use crate::release::{count_modes,load_asset_versions};
|
||||
|
||||
|
||||
#[expect(unused)]
|
||||
#[derive(Debug)]
|
||||
pub enum DownloadFutError{
|
||||
Download(crate::download::Error),
|
||||
Join(tokio::task::JoinError),
|
||||
Modes(crate::release::ModesError),
|
||||
}
|
||||
impl std::fmt::Display for DownloadFutError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for DownloadFutError{}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ErrorContext<E>{
|
||||
submission_id:u64,
|
||||
error:E,
|
||||
}
|
||||
impl<E:std::fmt::Debug> std::fmt::Display for ErrorContext<E>{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"SubmissionID({})={:?}",self.submission_id,self.error)
|
||||
}
|
||||
}
|
||||
impl<E:std::fmt::Debug> std::error::Error for ErrorContext<E>{}
|
||||
|
||||
async fn download_fut(
|
||||
cloud_context:&rbx_asset::cloud::Context,
|
||||
asset_version:rbx_asset::cloud::GetAssetVersionRequest,
|
||||
)->Result<u32,DownloadFutError>{
|
||||
// download
|
||||
let maybe_gzip=download_asset_version(cloud_context,asset_version)
|
||||
.await
|
||||
.map_err(DownloadFutError::Download)?;
|
||||
|
||||
// count modes in a green thread
|
||||
let modes=tokio::task::spawn_blocking(||
|
||||
count_modes(maybe_gzip)
|
||||
)
|
||||
.await
|
||||
.map_err(DownloadFutError::Join)?
|
||||
.map_err(DownloadFutError::Modes)?;
|
||||
|
||||
Ok::<_,DownloadFutError>(modes)
|
||||
}
|
||||
|
||||
#[expect(unused)]
|
||||
#[derive(Debug)]
|
||||
pub enum InnerError{
|
||||
Io(std::io::Error),
|
||||
LoadAssetVersions(crate::release::LoadAssetVersionsError),
|
||||
LoadAssetVersionsListLength,
|
||||
DownloadFutErrors(Vec<ErrorContext<DownloadFutError>>),
|
||||
ReleaseErrors(Vec<ErrorContext<tonic::Status>>),
|
||||
}
|
||||
impl std::fmt::Display for InnerError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for InnerError{}
|
||||
|
||||
const MAX_PARALLEL_DECODE:usize=6;
|
||||
const MAX_CONCURRENT_RELEASE:usize=16;
|
||||
|
||||
async fn release_inner(
|
||||
release_info:ReleaseSubmissionsBatchRequest,
|
||||
cloud_context:&rbx_asset::cloud::Context,
|
||||
cloud_context_luau_execution:&rbx_asset::cloud::Context,
|
||||
load_asset_version_runtime:&rbx_asset::cloud::LuauSessionLatestRequest,
|
||||
submissions:&crate::grpc::submissions::Service,
|
||||
)->Result<(),InnerError>{
|
||||
let available_parallelism=std::thread::available_parallelism().map_err(InnerError::Io)?.get();
|
||||
// set up futures
|
||||
|
||||
// unnecessary allocation :(
|
||||
let asset_versions:Vec<_> =release_info
|
||||
.Submissions
|
||||
.iter()
|
||||
.map(|submission|rbx_asset::cloud::GetAssetVersionRequest{
|
||||
asset_id:submission.ModelID,
|
||||
version:submission.ModelVersion,
|
||||
})
|
||||
.enumerate()
|
||||
.collect();
|
||||
|
||||
// fut_download
|
||||
let fut_download=futures::stream::iter(asset_versions)
|
||||
.map(|(index,asset_version)|async move{
|
||||
let modes=download_fut(cloud_context,asset_version).await;
|
||||
(index,modes)
|
||||
})
|
||||
.buffer_unordered(available_parallelism.min(MAX_PARALLEL_DECODE))
|
||||
.collect::<Vec<(usize,Result<_,DownloadFutError>)>>();
|
||||
|
||||
// fut_luau
|
||||
let fut_load_asset_versions=load_asset_versions(
|
||||
cloud_context_luau_execution,
|
||||
load_asset_version_runtime,
|
||||
release_info.Submissions.iter().map(|submission|submission.UploadedAssetID),
|
||||
);
|
||||
|
||||
// execute futures
|
||||
let (mut modes_unordered,load_asset_versions_result)=tokio::join!(fut_download,fut_load_asset_versions);
|
||||
|
||||
let load_asset_versions=load_asset_versions_result.map_err(InnerError::LoadAssetVersions)?;
|
||||
|
||||
// sanity check roblox output
|
||||
if load_asset_versions.len()!=release_info.Submissions.len(){
|
||||
return Err(InnerError::LoadAssetVersionsListLength);
|
||||
};
|
||||
|
||||
// rip asymptotic complexity (hash map would be better)
|
||||
modes_unordered.sort_by_key(|&(index,_)|index);
|
||||
|
||||
// check modes calculations for all success
|
||||
let mut modes=Vec::with_capacity(modes_unordered.len());
|
||||
let mut errors=Vec::with_capacity(modes_unordered.len());
|
||||
for (index,result) in modes_unordered{
|
||||
match result{
|
||||
Ok(value)=>modes.push(value),
|
||||
Err(error)=>errors.push(ErrorContext{
|
||||
submission_id:release_info.Submissions[index].SubmissionID,
|
||||
error:error,
|
||||
}),
|
||||
}
|
||||
}
|
||||
if !errors.is_empty(){
|
||||
return Err(InnerError::DownloadFutErrors(errors));
|
||||
}
|
||||
|
||||
// concurrently dispatch results
|
||||
let release_results:Vec<_> =futures::stream::iter(
|
||||
release_info
|
||||
.Submissions
|
||||
.into_iter()
|
||||
.zip(modes)
|
||||
.zip(load_asset_versions)
|
||||
.map(|((submission,modes),asset_version)|async move{
|
||||
let result=submissions.set_status_released(rust_grpc::validator::SubmissionReleaseRequest{
|
||||
submission_id:submission.SubmissionID,
|
||||
map_create:Some(rust_grpc::maps_extended::MapCreate{
|
||||
id:submission.UploadedAssetID as i64,
|
||||
display_name:submission.DisplayName,
|
||||
creator:submission.Creator,
|
||||
game_id:submission.GameID,
|
||||
date:submission.ReleaseDate,
|
||||
submitter:submission.Submitter,
|
||||
thumbnail:0,
|
||||
asset_version,
|
||||
modes,
|
||||
}),
|
||||
}).await;
|
||||
(submission.SubmissionID,result)
|
||||
})
|
||||
)
|
||||
.buffer_unordered(MAX_CONCURRENT_RELEASE)
|
||||
.collect().await;
|
||||
|
||||
// check for errors
|
||||
let errors:Vec<_> =
|
||||
release_results
|
||||
.into_iter()
|
||||
.filter_map(|(submission_id,result)|
|
||||
result.err().map(|e|ErrorContext{
|
||||
submission_id,
|
||||
error:e,
|
||||
})
|
||||
)
|
||||
.collect();
|
||||
|
||||
if !errors.is_empty(){
|
||||
return Err(InnerError::ReleaseErrors(errors));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
UpdateOperation(tonic::Status),
|
||||
}
|
||||
impl std::fmt::Display for Error{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for Error{}
|
||||
|
||||
impl crate::message_handler::MessageHandler{
|
||||
pub async fn release_submissions_batch(&self,release_info:ReleaseSubmissionsBatchRequest)->Result<(),Error>{
|
||||
let operation_id=release_info.OperationID;
|
||||
let result=release_inner(
|
||||
release_info,
|
||||
&self.cloud_context,
|
||||
&self.cloud_context_luau_execution,
|
||||
&self.load_asset_version_runtime,
|
||||
&self.submissions,
|
||||
).await;
|
||||
|
||||
match result{
|
||||
Ok(())=>{
|
||||
// operation success
|
||||
self.operations.success(rust_grpc::validator::OperationSuccessRequest{
|
||||
operation_id,
|
||||
path:String::new(),
|
||||
}).await.map_err(Error::UpdateOperation)?;
|
||||
},
|
||||
Err(e)=>{
|
||||
// operation error
|
||||
self.operations.fail(rust_grpc::validator::OperationFailRequest{
|
||||
operation_id,
|
||||
status_message:e.to_string(),
|
||||
}).await.map_err(Error::UpdateOperation)?;
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -3,27 +3,50 @@ use crate::nats_types::UploadMapfixRequest;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
pub enum InnerError{
|
||||
Download(crate::download::Error),
|
||||
IO(std::io::Error),
|
||||
Json(serde_json::Error),
|
||||
Upload(rbx_asset::cookie::UploadError),
|
||||
ApiActionMapfixUploaded(tonic::Status),
|
||||
ModelFileDecode(crate::rbx_util::ReadDomError),
|
||||
GetRootInstance(crate::rbx_util::GetRootInstanceError),
|
||||
NonSequentialModes,
|
||||
TooManyModes(usize),
|
||||
CreateSession(rbx_asset::cloud::CreateError),
|
||||
NonPositiveNumber(serde_json::Number),
|
||||
Script(rbx_asset::cloud::LuauError),
|
||||
InvalidResult(Vec<serde_json::Value>),
|
||||
LuauSession(rbx_asset::cloud::LuauSessionError),
|
||||
GetAssetInfo(rbx_asset::cloud::GetError),
|
||||
RevisionMismatch{
|
||||
after:u64,
|
||||
before:u64,
|
||||
},
|
||||
}
|
||||
impl std::fmt::Display for InnerError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for InnerError{}
|
||||
|
||||
async fn upload_inner(
|
||||
upload_info:UploadMapfixRequest,
|
||||
cloud_context:&rbx_asset::cloud::Context,
|
||||
cookie_context:&rbx_asset::cookie::Context,
|
||||
group_id:Option<u64>,
|
||||
)->Result<(),InnerError>{
|
||||
// download the map model
|
||||
let maybe_gzip=download_asset_version(cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
|
||||
asset_id:upload_info.ModelID,
|
||||
version:upload_info.ModelVersion,
|
||||
}).await.map_err(InnerError::Download)?;
|
||||
|
||||
// transparently handle gzipped models
|
||||
let model_data=maybe_gzip.to_vec().map_err(InnerError::IO)?;
|
||||
|
||||
// upload the map to the strafesnet group
|
||||
let _upload_response=cookie_context.upload(rbx_asset::cookie::UploadRequest{
|
||||
assetid:upload_info.TargetAssetID,
|
||||
groupId:group_id,
|
||||
name:None,
|
||||
description:None,
|
||||
ispublic:None,
|
||||
allowComments:None,
|
||||
},model_data).await.map_err(InnerError::Upload)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
ApiActionMapfixUploaded(tonic::Status),
|
||||
}
|
||||
impl std::fmt::Display for Error{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
@@ -34,105 +57,40 @@ impl std::error::Error for Error{}
|
||||
|
||||
impl crate::message_handler::MessageHandler{
|
||||
pub async fn upload_mapfix(&self,upload_info:UploadMapfixRequest)->Result<(),Error>{
|
||||
// download the map model
|
||||
let maybe_gzip=download_asset_version(&self.cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
|
||||
asset_id:upload_info.ModelID,
|
||||
version:upload_info.ModelVersion,
|
||||
}).await.map_err(Error::Download)?;
|
||||
let mapfix_id=upload_info.MapfixID;
|
||||
let result=upload_inner(
|
||||
upload_info,
|
||||
&self.cloud_context,
|
||||
&self.cookie_context,
|
||||
self.group_id,
|
||||
).await;
|
||||
|
||||
// transparently handle gzipped models
|
||||
let model_data=maybe_gzip.to_vec().map_err(Error::IO)?;
|
||||
|
||||
// upload the map to the strafesnet group
|
||||
let upload_response=self.cookie_context.upload(rbx_asset::cookie::UploadRequest{
|
||||
assetid:upload_info.TargetAssetID,
|
||||
groupId:self.group_id,
|
||||
name:None,
|
||||
description:None,
|
||||
ispublic:None,
|
||||
allowComments:None,
|
||||
},model_data.clone()).await.map_err(Error::Upload)?;
|
||||
|
||||
// mark mapfix as uploaded, TargetAssetID is unchanged
|
||||
self.mapfixes.set_status_uploaded(rust_grpc::validator::MapfixId{
|
||||
id:upload_info.MapfixID,
|
||||
}).await.map_err(Error::ApiActionMapfixUploaded)?;
|
||||
|
||||
// count modes
|
||||
|
||||
// decode dom (slow!)
|
||||
let dom=crate::rbx_util::read_dom(model_data.as_slice()).map_err(Error::ModelFileDecode)?;
|
||||
|
||||
// extract the root instance
|
||||
let model_instance=crate::rbx_util::get_root_instance(&dom).map_err(Error::GetRootInstance)?;
|
||||
|
||||
// extract information from the model
|
||||
let model_info=crate::check::get_model_info(&dom,model_instance);
|
||||
|
||||
// count modes
|
||||
let modes=model_info.count_modes().ok_or(Error::NonSequentialModes)?;
|
||||
|
||||
// hard limit LOL
|
||||
let modes=if modes<u32::MAX as usize{
|
||||
modes as u32
|
||||
}else{
|
||||
return Err(Error::TooManyModes(modes));
|
||||
};
|
||||
|
||||
// update asset version and modes using Roblox Luau API
|
||||
let script=format!("return game:GetService(\"InsertService\"):GetLatestAssetVersionAsync({})",upload_info.TargetAssetID);
|
||||
let request=rbx_asset::cloud::LuauSessionLatestRequest{
|
||||
place_id:self.load_asset_version_place_id,
|
||||
universe_id:self.load_asset_version_universe_id,
|
||||
};
|
||||
let session=rbx_asset::cloud::LuauSessionCreate{
|
||||
script:&script,
|
||||
user:None,
|
||||
timeout:None,
|
||||
binaryInput:None,
|
||||
enableBinaryOutput:None,
|
||||
binaryOutputUri:None,
|
||||
};
|
||||
let session_response=self.cloud_context.create_luau_session(&request,session).await.map_err(Error::CreateSession)?;
|
||||
|
||||
let result=crate::rbx_util::get_luau_result_exp_backoff(&self.cloud_context,&session_response).await;
|
||||
|
||||
let load_asset_version=match result{
|
||||
Ok(Ok(rbx_asset::cloud::LuauResults{results}))=>match results.as_slice(){
|
||||
[serde_json::Value::Number(load_asset_version)]=>load_asset_version.as_u64().ok_or_else(||Error::NonPositiveNumber(load_asset_version.clone())),
|
||||
_=>Err(Error::InvalidResult(results))
|
||||
// update the mapfix depending on the result
|
||||
match result{
|
||||
Ok(())=>{
|
||||
// mark mapfix as uploaded, TargetAssetID is unchanged
|
||||
self.mapfixes.set_status_uploaded(rust_grpc::validator::MapfixId{
|
||||
id:mapfix_id,
|
||||
}).await.map_err(Error::ApiActionMapfixUploaded)?;
|
||||
},
|
||||
Ok(Err(e))=>Err(Error::Script(e)),
|
||||
Err(e)=>Err(Error::LuauSession(e)),
|
||||
}?;
|
||||
Err(e)=>{
|
||||
// log error
|
||||
println!("[upload_mapfix] Error: {e}");
|
||||
|
||||
// check asset version to make sure it hasn't been updated
|
||||
let asset_response=self.cloud_context.get_asset_info(rbx_asset::cloud::GetAssetLatestRequest{
|
||||
asset_id:upload_info.TargetAssetID,
|
||||
}).await.map_err(Error::GetAssetInfo)?;
|
||||
self.mapfixes.create_audit_error(
|
||||
rust_grpc::validator::AuditErrorRequest{
|
||||
id:mapfix_id,
|
||||
error_message:e.to_string(),
|
||||
}
|
||||
).await.map_err(Error::ApiActionMapfixUploaded)?;
|
||||
|
||||
if upload_response.AssetVersion!=asset_response.revisionId{
|
||||
// the model was updated while we were fetching LoadAssetVersion.
|
||||
// the number we got may be invalid.
|
||||
return Err(Error::RevisionMismatch{
|
||||
before:upload_response.AssetVersion,
|
||||
after:asset_response.revisionId,
|
||||
});
|
||||
// update the mapfix model status to accepted
|
||||
self.mapfixes.set_status_not_uploaded(rust_grpc::validator::MapfixId{
|
||||
id:mapfix_id,
|
||||
}).await.map_err(Error::ApiActionMapfixUploaded)?;
|
||||
},
|
||||
}
|
||||
|
||||
// write AssetVersion directly to map
|
||||
self.maps_extended.update(rust_grpc::maps_extended::MapUpdate{
|
||||
id:upload_info.TargetAssetID as i64,
|
||||
asset_version:Some(load_asset_version),
|
||||
modes:Some(modes),
|
||||
display_name:None,
|
||||
creator:None,
|
||||
game_id:None,
|
||||
date:None,
|
||||
submitter:None,
|
||||
thumbnail:None,
|
||||
}).await.map_err(Error::ApiActionMapfixUploaded)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,50 @@ use crate::nats_types::UploadSubmissionRequest;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
pub enum InnerError{
|
||||
Download(crate::download::Error),
|
||||
IO(std::io::Error),
|
||||
Json(serde_json::Error),
|
||||
Create(rbx_asset::cookie::CreateError),
|
||||
SystemTime(std::time::SystemTimeError),
|
||||
}
|
||||
impl std::fmt::Display for InnerError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for InnerError{}
|
||||
|
||||
async fn upload_inner(
|
||||
upload_info:UploadSubmissionRequest,
|
||||
cloud_context:&rbx_asset::cloud::Context,
|
||||
cookie_context:&rbx_asset::cookie::Context,
|
||||
group_id:Option<u64>,
|
||||
)->Result<u64,InnerError>{
|
||||
// download the map model
|
||||
let maybe_gzip=download_asset_version(cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
|
||||
asset_id:upload_info.ModelID,
|
||||
version:upload_info.ModelVersion,
|
||||
}).await.map_err(InnerError::Download)?;
|
||||
|
||||
// transparently handle gzipped models
|
||||
let model_data=maybe_gzip.to_vec().map_err(InnerError::IO)?;
|
||||
|
||||
// upload the map to the strafesnet group
|
||||
let upload_response=cookie_context.create(rbx_asset::cookie::CreateRequest{
|
||||
name:upload_info.ModelName.clone(),
|
||||
description:"".to_owned(),
|
||||
ispublic:false,
|
||||
allowComments:false,
|
||||
groupId:group_id,
|
||||
},model_data).await.map_err(InnerError::Create)?;
|
||||
|
||||
Ok(upload_response.AssetId)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
ApiActionSubmissionUploaded(tonic::Status),
|
||||
}
|
||||
impl std::fmt::Display for Error{
|
||||
@@ -20,29 +58,40 @@ impl std::error::Error for Error{}
|
||||
|
||||
impl crate::message_handler::MessageHandler{
|
||||
pub async fn upload_submission(&self,upload_info:UploadSubmissionRequest)->Result<(),Error>{
|
||||
// download the map model
|
||||
let maybe_gzip=download_asset_version(&self.cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
|
||||
asset_id:upload_info.ModelID,
|
||||
version:upload_info.ModelVersion,
|
||||
}).await.map_err(Error::Download)?;
|
||||
let submission_id=upload_info.SubmissionID;
|
||||
let result=upload_inner(
|
||||
upload_info,
|
||||
&self.cloud_context,
|
||||
&self.cookie_context,
|
||||
self.group_id,
|
||||
).await;
|
||||
|
||||
// transparently handle gzipped models
|
||||
let model_data=maybe_gzip.to_vec().map_err(Error::IO)?;
|
||||
// update the submission depending on the result
|
||||
match result{
|
||||
Ok(uploaded_asset_id)=>{
|
||||
// note the asset id of the created model for later release, and mark the submission as uploaded
|
||||
self.submissions.set_status_uploaded(rust_grpc::validator::StatusUploadedRequest{
|
||||
id:submission_id,
|
||||
uploaded_asset_id,
|
||||
}).await.map_err(Error::ApiActionSubmissionUploaded)?;
|
||||
},
|
||||
Err(e)=>{
|
||||
// log error
|
||||
println!("[upload_submission] Error: {e}");
|
||||
|
||||
// upload the map to the strafesnet group
|
||||
let upload_response=self.cookie_context.create(rbx_asset::cookie::CreateRequest{
|
||||
name:upload_info.ModelName.clone(),
|
||||
description:"".to_owned(),
|
||||
ispublic:false,
|
||||
allowComments:false,
|
||||
groupId:self.group_id,
|
||||
},model_data).await.map_err(Error::Create)?;
|
||||
self.submissions.create_audit_error(
|
||||
rust_grpc::validator::AuditErrorRequest{
|
||||
id:submission_id,
|
||||
error_message:e.to_string(),
|
||||
}
|
||||
).await.map_err(Error::ApiActionSubmissionUploaded)?;
|
||||
|
||||
// note the asset id of the created model for later release, and mark the submission as uploaded
|
||||
self.submissions.set_status_uploaded(rust_grpc::validator::StatusUploadedRequest{
|
||||
id:upload_info.SubmissionID,
|
||||
uploaded_asset_id:upload_response.AssetId,
|
||||
}).await.map_err(Error::ApiActionSubmissionUploaded)?;
|
||||
// update the submission model status to accepted
|
||||
self.submissions.set_status_not_uploaded(rust_grpc::validator::SubmissionId{
|
||||
id:submission_id,
|
||||
}).await.map_err(Error::ApiActionSubmissionUploaded)?;
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ impl crate::message_handler::MessageHandler{
|
||||
).await.map_err(Error::ApiActionMapfixValidate)?;
|
||||
|
||||
// update the mapfix model status to accepted
|
||||
self.mapfixes.set_status_failed(rust_grpc::validator::MapfixId{
|
||||
self.mapfixes.set_status_not_validated(rust_grpc::validator::MapfixId{
|
||||
id:mapfix_id,
|
||||
}).await.map_err(Error::ApiActionMapfixValidate)?;
|
||||
},
|
||||
|
||||
@@ -37,7 +37,7 @@ impl crate::message_handler::MessageHandler{
|
||||
).await.map_err(Error::ApiActionSubmissionValidate)?;
|
||||
|
||||
// update the submission model status to accepted
|
||||
self.submissions.set_status_failed(rust_grpc::validator::SubmissionId{
|
||||
self.submissions.set_status_not_validated(rust_grpc::validator::SubmissionId{
|
||||
id:submission_id,
|
||||
}).await.map_err(Error::ApiActionSubmissionValidate)?;
|
||||
},
|
||||
|
||||
@@ -30,6 +30,8 @@ const ReviewActions = {
|
||||
RequestChanges: {name:"Request Changes",action:"request-changes"} as ReviewAction,
|
||||
Upload: {name:"Upload",action:"trigger-upload"} as ReviewAction,
|
||||
ResetUploading: {name:"Reset Uploading",action:"reset-uploading"} as ReviewAction,
|
||||
Release: {name:"Release",action:"trigger-release"} as ReviewAction,
|
||||
ResetReleasing: {name:"Reset Releasing",action:"reset-releasing"} as ReviewAction,
|
||||
}
|
||||
|
||||
const ReviewButtons: React.FC<ReviewButtonsProps> = ({
|
||||
@@ -54,6 +56,7 @@ const ReviewButtons: React.FC<ReviewButtonsProps> = ({
|
||||
|
||||
const reviewRole = type === "submission" ? RolesConstants.SubmissionReview : RolesConstants.MapfixReview;
|
||||
const uploadRole = type === "submission" ? RolesConstants.SubmissionUpload : RolesConstants.MapfixUpload;
|
||||
const releaseRole = type === "submission" ? RolesConstants.SubmissionRelease : RolesConstants.MapfixRelease;
|
||||
|
||||
if (is_submitter) {
|
||||
if (StatusMatches(status, [Status.UnderConstruction, Status.ChangesRequested])) {
|
||||
@@ -139,6 +142,24 @@ const ReviewButtons: React.FC<ReviewButtonsProps> = ({
|
||||
}
|
||||
}
|
||||
|
||||
// Buttons for release role
|
||||
if (hasRole(roles, releaseRole)) {
|
||||
// submissions do not have a release button
|
||||
if (type === "mapfix" && status === Status.Uploaded) {
|
||||
buttons.push({
|
||||
action: ReviewActions.Release,
|
||||
color: "success"
|
||||
});
|
||||
}
|
||||
|
||||
if (status === Status.Releasing) {
|
||||
buttons.push({
|
||||
action: ReviewActions.ResetReleasing,
|
||||
color: "warning"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return buttons;
|
||||
};
|
||||
|
||||
|
||||
@@ -8,8 +8,9 @@ const enum MapfixStatus {
|
||||
Validated = 6,
|
||||
Uploading = 7,
|
||||
Uploaded = 8,
|
||||
Releasing = 11,
|
||||
Rejected = 9,
|
||||
// MapfixStatus does not have a Released state
|
||||
Released = 10,
|
||||
}
|
||||
|
||||
interface MapfixInfo {
|
||||
@@ -36,8 +37,12 @@ interface MapfixList {
|
||||
|
||||
function MapfixStatusToString(mapfix_status: MapfixStatus): string {
|
||||
switch (mapfix_status) {
|
||||
case MapfixStatus.Released:
|
||||
return "RELEASED"
|
||||
case MapfixStatus.Rejected:
|
||||
return "REJECTED"
|
||||
case MapfixStatus.Releasing:
|
||||
return "RELEASING"
|
||||
case MapfixStatus.Uploading:
|
||||
return "UPLOADING"
|
||||
case MapfixStatus.Uploaded:
|
||||
@@ -47,7 +52,7 @@ function MapfixStatusToString(mapfix_status: MapfixStatus): string {
|
||||
case MapfixStatus.Validating:
|
||||
return "VALIDATING"
|
||||
case MapfixStatus.AcceptedUnvalidated:
|
||||
return "ACCEPTED, NOT VALIDATED"
|
||||
return "SCRIPT REVIEW"
|
||||
case MapfixStatus.ChangesRequested:
|
||||
return "CHANGES REQUESTED"
|
||||
case MapfixStatus.Submitted:
|
||||
|
||||
@@ -9,6 +9,7 @@ const RolesConstants = {
|
||||
ScriptWrite: 1 << 3 as Roles,
|
||||
MapfixUpload: 1 << 2 as Roles,
|
||||
MapfixReview: 1 << 1 as Roles,
|
||||
MapfixRelease: 1 << 2 as Roles, // same as upload
|
||||
MapDownload: 1 << 0 as Roles,
|
||||
Empty: 0 as Roles,
|
||||
};
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import {SubmissionStatus} from "@/app/ts/Submission";
|
||||
import {MapfixStatus} from "@/app/ts/Mapfix";
|
||||
|
||||
export const Status = {
|
||||
UnderConstruction: SubmissionStatus.UnderConstruction,
|
||||
ChangesRequested: SubmissionStatus.ChangesRequested,
|
||||
Submitting: SubmissionStatus.Submitting,
|
||||
Submitted: SubmissionStatus.Submitted,
|
||||
AcceptedUnvalidated: SubmissionStatus.AcceptedUnvalidated,
|
||||
Validating: SubmissionStatus.Validating,
|
||||
Validated: SubmissionStatus.Validated,
|
||||
Uploading: SubmissionStatus.Uploading,
|
||||
Uploaded: SubmissionStatus.Uploaded,
|
||||
Rejected: SubmissionStatus.Rejected,
|
||||
Release: SubmissionStatus.Released
|
||||
UnderConstruction: MapfixStatus.UnderConstruction,
|
||||
ChangesRequested: MapfixStatus.ChangesRequested,
|
||||
Submitting: MapfixStatus.Submitting,
|
||||
Submitted: MapfixStatus.Submitted,
|
||||
AcceptedUnvalidated: MapfixStatus.AcceptedUnvalidated,
|
||||
Validating: MapfixStatus.Validating,
|
||||
Validated: MapfixStatus.Validated,
|
||||
Uploading: MapfixStatus.Uploading,
|
||||
Uploaded: MapfixStatus.Uploaded,
|
||||
Rejected: MapfixStatus.Rejected,
|
||||
Release: MapfixStatus.Released,
|
||||
Releasing: MapfixStatus.Releasing,
|
||||
};
|
||||
|
||||
export const StatusMatches = (status: number, statusValues: number[]) => {
|
||||
return statusValues.includes(status);
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user