forked from StrafesNET/maps-service
Compare commits
148 Commits
validator-
...
uint
| Author | SHA1 | Date | |
|---|---|---|---|
|
0324a57e5c
|
|||
|
ca750669db
|
|||
|
ccf1ff6866
|
|||
|
1f1deacc2d
|
|||
|
d8095cee83
|
|||
|
28985bed55
|
|||
|
a03e812e46
|
|||
|
7334e88b55
|
|||
|
b93c813dec
|
|||
|
926a90329b
|
|||
|
18abbd92ce
|
|||
|
c923a8a076
|
|||
|
d6da6f003e
|
|||
|
0dc7aec395
|
|||
|
c85cb63639
|
|||
|
6c865e8841
|
|||
|
99a082afb5
|
|||
|
434cd295f5
|
|||
|
bfc2a2cbca
|
|||
|
c24db2c3a0
|
|||
|
68f2311658
|
|||
|
163412a253
|
|||
|
044033cabf
|
|||
|
219a15f656
|
|||
|
383bc783a4
|
|||
|
24a5baae77
|
|||
|
4ba3b5cd01
|
|||
|
f610fc1c0f
|
|||
|
e67d679901
|
|||
|
3c3d09c4a7
|
|||
|
d02e3776f3
|
|||
|
77222c84db
|
|||
|
412f34817c
|
|||
|
cac288d73b
|
|||
|
29e414d6e7
|
|||
|
c9ba2e3e6e
|
|||
|
0666685a49
|
|||
|
ff9237e453
|
|||
|
9b5f7e0b0c
|
|||
|
e28c7e8149
|
|||
|
220ea84e22
|
|||
|
7648f407c5
|
|||
|
e0266c5d24
|
|||
|
9ab2e23fa9
|
|||
|
6b2f5e29e7
|
|||
|
d42e89fcb4
|
|||
|
7e881e6ac5
|
|||
|
2d57b945f2
|
|||
|
005e99424e
|
|||
|
a330b1c43b
|
|||
|
d2662eb833
|
|||
|
3ba599114d
|
|||
| d53f61fb5b | |||
|
5d259e20f2
|
|||
|
21b6903943
|
|||
|
14c7979310
|
|||
|
e376e02dc1
|
|||
|
4e7ee9dc5a
|
|||
|
ceaec14242
|
|||
|
9372caa157
|
|||
|
f73c274367
|
|||
|
c50a28443e
|
|||
|
c7150f1e23
|
|||
|
f16a817da2
|
|||
|
e858d252ab
|
|||
|
66e0d22ccd
|
|||
|
986ecfc7ad
|
|||
|
66890ccd44
|
|||
| ec15c1f2e5 | |||
|
8be9475ee5
|
|||
|
0cb2bec6e0
|
|||
| cf1906acaa | |||
|
7e93807298
|
|||
|
ee5b3331b4
|
|||
|
29c0acf3b2
|
|||
|
a844c4e90a
|
|||
|
5ed15a6847
|
|||
|
1ff1cae709
|
|||
|
|
c6ebe5a360 | ||
|
15dd6b4178
|
|||
|
ca1676db00
|
|||
|
56681f8862
|
|||
|
fe2c20bd72
|
|||
|
027a55661b
|
|||
|
a3d644f572
|
|||
|
d0634fc141
|
|||
| 719ef95b6d | |||
| c9041168e5 | |||
| 1e012af52e | |||
| 54b4cf2d13 | |||
|
|
91ac3a5e36 | ||
|
|
fc5519e744 | ||
| 170e194ac9 | |||
|
|
739c9354a6 | ||
| 73f559f049 | |||
|
|
3f377f4605 | ||
|
|
edc1ed5459 | ||
|
c9212a5ec8
|
|||
|
|
adaa088efe | ||
|
e85e3f130f
|
|||
| 0462788c53 | |||
| 2c31a9585b | |||
| 3699ce5cbb | |||
| 8776936e96 | |||
| e466af7d27 | |||
| abed5c6227 | |||
| a639b81988 | |||
| 5aa27c08a5 | |||
| 577ab5cdd0 | |||
| a72be13843 | |||
| d4e8edbb6e | |||
| 19c4e36990 | |||
| 56dec20189 | |||
| 34d37d8c1c | |||
| 508d41506a | |||
| 493c6d084a | |||
| 722ac5178f | |||
| df39101102 | |||
| e877ba4788 | |||
|
|
8a28d6cfcf | ||
|
e9f79241f1
|
|||
|
bfd287f3cc
|
|||
|
082c573ffb
|
|||
|
3bda4803aa
|
|||
|
c401d24366
|
|||
|
a119c4292e
|
|||
|
4cf7889db9
|
|||
|
146d627534
|
|||
|
97180ab263
|
|||
|
37560ac5d2
|
|||
|
de8f869b5b
|
|||
|
b6ae600a93
|
|||
|
96ace736f4
|
|||
|
9dd7a41d8f
|
|||
|
cc7df064be
|
|||
|
732598266c
|
|||
|
6d420c3a82
|
|||
|
2e65d071e0
|
|||
|
e36b49a31e
|
|||
|
1d7f6ea79a
|
|||
|
b0f1e42a06
|
|||
|
8925d71bcd
|
|||
|
8de5bcba68
|
|||
|
a048d713da
|
|||
|
581c65594d
|
|||
|
4e22933e34
|
|||
|
758c2254eb
|
|||
|
ade54ee662
|
68
.drone.yml
68
.drone.yml
@@ -25,6 +25,8 @@ steps:
|
||||
branch:
|
||||
- master
|
||||
- staging
|
||||
event:
|
||||
- push
|
||||
|
||||
- name: frontend
|
||||
image: plugins/docker
|
||||
@@ -44,6 +46,8 @@ steps:
|
||||
branch:
|
||||
- master
|
||||
- staging
|
||||
event:
|
||||
- push
|
||||
|
||||
- name: validator
|
||||
image: plugins/docker
|
||||
@@ -63,6 +67,8 @@ steps:
|
||||
branch:
|
||||
- master
|
||||
- staging
|
||||
event:
|
||||
- push
|
||||
|
||||
- name: deploy
|
||||
image: argoproj/argocd:latest
|
||||
@@ -84,8 +90,68 @@ steps:
|
||||
branch:
|
||||
- master
|
||||
- staging
|
||||
event:
|
||||
- push
|
||||
|
||||
# pr dry run
|
||||
- name: api-pr
|
||||
image: plugins/docker
|
||||
settings:
|
||||
registry: registry.itzana.me
|
||||
repo: registry.itzana.me/strafesnet/maptest-validator
|
||||
tags:
|
||||
- ${DRONE_BRANCH}-${DRONE_BUILD_NUMBER}
|
||||
- ${DRONE_BRANCH}
|
||||
dockerfile: Containerfile
|
||||
context: .
|
||||
dry_run: true
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
|
||||
- name: frontend-pr
|
||||
image: plugins/docker
|
||||
settings:
|
||||
registry: registry.itzana.me
|
||||
repo: registry.itzana.me/strafesnet/maptest-validator
|
||||
tags:
|
||||
- ${DRONE_BRANCH}-${DRONE_BUILD_NUMBER}
|
||||
- ${DRONE_BRANCH}
|
||||
dockerfile: web/Containerfile
|
||||
context: web
|
||||
dry_run: true
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
|
||||
- name: validator-pr
|
||||
image: plugins/docker
|
||||
settings:
|
||||
registry: registry.itzana.me
|
||||
repo: registry.itzana.me/strafesnet/maptest-validator
|
||||
tags:
|
||||
- ${DRONE_BRANCH}-${DRONE_BUILD_NUMBER}
|
||||
- ${DRONE_BRANCH}
|
||||
dockerfile: validation/Containerfile
|
||||
context: validation
|
||||
dry_run: true
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
|
||||
- name: build-pr
|
||||
image: alpine
|
||||
commands:
|
||||
- echo "Success!"
|
||||
depends_on:
|
||||
- api-pr
|
||||
- frontend-pr
|
||||
- validator-pr
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
---
|
||||
kind: signature
|
||||
hmac: 1162b329a9cad12b4c5db0ccf8b8998072b0de9279326f76a493fd0af6794095
|
||||
hmac: 11e6d7f1eb839d3798fdcb642ca5523c011bd14c1f3a0343a9c3106bab9ef142
|
||||
|
||||
...
|
||||
|
||||
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -1297,9 +1297,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rbx_asset"
|
||||
version = "0.2.5"
|
||||
version = "0.4.3"
|
||||
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
|
||||
checksum = "dcf243f46bd41b3880a27278177a3f9996f95ab231d9a04345ad9dd381c3a54a"
|
||||
checksum = "077e2a0b201a777dfd2ff822766ae7d0c8c3003206115da57f7bce15ee73cbc7"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"flate2",
|
||||
@@ -1798,7 +1798,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "submissions-api"
|
||||
version = "0.6.1"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"reqwest",
|
||||
"serde",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Stage 1: Build
|
||||
FROM docker.io/golang:1.23 AS builder
|
||||
FROM registry.itzana.me/docker-proxy/golang:1.24 AS builder
|
||||
|
||||
# Set the working directory in the container
|
||||
WORKDIR /app
|
||||
@@ -14,7 +14,7 @@ COPY . .
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -o service ./cmd/maps-service/service.go
|
||||
|
||||
# Stage 2: Run
|
||||
FROM alpine
|
||||
FROM registry.itzana.me/docker-proxy/alpine:3.21
|
||||
|
||||
# Set up a non-root user for security
|
||||
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
|
||||
|
||||
@@ -4,9 +4,191 @@ info:
|
||||
description: Internal operations inaccessible from the public internet.
|
||||
version: 0.1.0
|
||||
tags:
|
||||
- name: Mapfixes
|
||||
description: Mapfix operations
|
||||
- name: Submissions
|
||||
description: Submission operations
|
||||
paths:
|
||||
/mapfixes:
|
||||
post:
|
||||
summary: Create a mapfix
|
||||
operationId: createMapfix
|
||||
tags:
|
||||
- Mapfixes
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/MapfixCreate'
|
||||
responses:
|
||||
"201":
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/MapfixID"
|
||||
default:
|
||||
description: General Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/mapfixes/{MapfixID}/validated-model:
|
||||
post:
|
||||
summary: Update validated model
|
||||
operationId: updateMapfixValidatedModel
|
||||
tags:
|
||||
- Mapfixes
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/MapfixID'
|
||||
- name: ValidatedModelID
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
- name: ValidatedModelVersion
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
responses:
|
||||
"204":
|
||||
description: Successful response
|
||||
default:
|
||||
description: General Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/mapfixes/{MapfixID}/status/validator-submitted:
|
||||
post:
|
||||
summary: (Internal endpoint) Role Validator changes status from Submitting -> Submitted
|
||||
operationId: actionMapfixSubmitted
|
||||
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/validator-validated:
|
||||
post:
|
||||
summary: (Internal endpoint) Role Validator changes status from Validating -> Validated
|
||||
operationId: actionMapfixValidated
|
||||
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/validator-failed:
|
||||
post:
|
||||
summary: (Internal endpoint) Role Validator changes status from Validating -> Accepted
|
||||
operationId: actionMapfixAccepted
|
||||
tags:
|
||||
- Mapfixes
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/MapfixID'
|
||||
- name: StatusMessage
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
minLength: 0
|
||||
maxLength: 4096
|
||||
responses:
|
||||
"204":
|
||||
description: Successful response
|
||||
default:
|
||||
description: General Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/mapfixes/{MapfixID}/status/validator-uploaded:
|
||||
post:
|
||||
summary: (Internal endpoint) Role Validator changes status from Uploading -> 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}/status/operation-failed:
|
||||
post:
|
||||
summary: (Internal endpoint) Fail an operation and write a StatusMessage
|
||||
operationId: actionOperationFailed
|
||||
tags:
|
||||
- Operations
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/OperationID'
|
||||
- name: StatusMessage
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
minLength: 0
|
||||
maxLength: 4096
|
||||
responses:
|
||||
"204":
|
||||
description: Successful response
|
||||
default:
|
||||
description: General Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/submissions:
|
||||
post:
|
||||
summary: Create a new submission
|
||||
operationId: createSubmission
|
||||
tags:
|
||||
- Submissions
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SubmissionCreate'
|
||||
responses:
|
||||
"201":
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SubmissionID"
|
||||
default:
|
||||
description: General Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/submissions/{SubmissionID}/validated-model:
|
||||
post:
|
||||
summary: Update validated model
|
||||
@@ -20,13 +202,32 @@ paths:
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
- name: ValidatedModelVersion
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
responses:
|
||||
"204":
|
||||
description: Successful response
|
||||
default:
|
||||
description: General Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/submissions/{SubmissionID}/status/validator-submitted:
|
||||
post:
|
||||
summary: (Internal endpoint) Role Validator changes status from Submitting -> Submitted
|
||||
operationId: actionSubmissionSubmitted
|
||||
tags:
|
||||
- Submissions
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/SubmissionID'
|
||||
responses:
|
||||
"204":
|
||||
description: Successful response
|
||||
@@ -90,7 +291,8 @@ paths:
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
responses:
|
||||
"204":
|
||||
description: Successful response
|
||||
@@ -119,12 +321,14 @@ paths:
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
- name: Policy
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
format: uint32
|
||||
minimum: 0
|
||||
responses:
|
||||
"200":
|
||||
description: Successful response
|
||||
@@ -157,7 +361,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Id"
|
||||
$ref: "#/components/schemas/ScriptPolicyID"
|
||||
default:
|
||||
description: General Error
|
||||
content:
|
||||
@@ -189,11 +393,18 @@ paths:
|
||||
schema:
|
||||
type: string
|
||||
maxLength: 1048576
|
||||
- name: SubmissionID
|
||||
- name: ResourceType
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint32
|
||||
minimum: 0
|
||||
- name: ResourceID
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
responses:
|
||||
"200":
|
||||
description: Successful response
|
||||
@@ -226,7 +437,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Id"
|
||||
$ref: "#/components/schemas/ScriptID"
|
||||
default:
|
||||
description: General Error
|
||||
content:
|
||||
@@ -256,6 +467,24 @@ paths:
|
||||
$ref: "#/components/schemas/Error"
|
||||
components:
|
||||
parameters:
|
||||
MapfixID:
|
||||
name: MapfixID
|
||||
in: path
|
||||
required: true
|
||||
description: The unique identifier for a submission.
|
||||
schema:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
OperationID:
|
||||
name: OperationID
|
||||
in: path
|
||||
required: true
|
||||
description: The unique identifier for a long-running operation.
|
||||
schema:
|
||||
type: integer
|
||||
format: uint32
|
||||
minimum: 0
|
||||
SubmissionID:
|
||||
name: SubmissionID
|
||||
in: path
|
||||
@@ -263,7 +492,8 @@ components:
|
||||
description: The unique identifier for a submission.
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
ScriptID:
|
||||
name: ScriptID
|
||||
in: path
|
||||
@@ -271,14 +501,15 @@ components:
|
||||
description: The unique identifier for a script.
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
Page:
|
||||
name: Page
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
format: uint32
|
||||
minimum: 1
|
||||
Limit:
|
||||
name: Limit
|
||||
@@ -286,18 +517,125 @@ components:
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
format: uint32
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
schemas:
|
||||
Id:
|
||||
MapfixID:
|
||||
required:
|
||||
- ID
|
||||
- MapfixID
|
||||
type: object
|
||||
properties:
|
||||
ID:
|
||||
MapfixID:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
SubmissionID:
|
||||
required:
|
||||
- SubmissionID
|
||||
type: object
|
||||
properties:
|
||||
SubmissionID:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
ScriptID:
|
||||
required:
|
||||
- ScriptID
|
||||
type: object
|
||||
properties:
|
||||
ScriptID:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
ScriptPolicyID:
|
||||
required:
|
||||
- ScriptPolicyID
|
||||
type: object
|
||||
properties:
|
||||
ScriptPolicyID:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
MapfixCreate:
|
||||
required:
|
||||
- OperationID
|
||||
- AssetOwner
|
||||
- DisplayName
|
||||
- Creator
|
||||
- GameID
|
||||
- AssetID
|
||||
- AssetVersion
|
||||
- TargetAssetID
|
||||
type: object
|
||||
properties:
|
||||
OperationID:
|
||||
type: integer
|
||||
format: uint32
|
||||
minimum: 0
|
||||
AssetOwner:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
DisplayName:
|
||||
type: string
|
||||
maxLength: 128
|
||||
Creator:
|
||||
type: string
|
||||
maxLength: 128
|
||||
GameID:
|
||||
type: integer
|
||||
format: uint32
|
||||
minimum: 0
|
||||
AssetID:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
AssetVersion:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
TargetAssetID:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
SubmissionCreate:
|
||||
required:
|
||||
- OperationID
|
||||
- AssetOwner
|
||||
- DisplayName
|
||||
- Creator
|
||||
- GameID
|
||||
- AssetID
|
||||
- AssetVersion
|
||||
type: object
|
||||
properties:
|
||||
OperationID:
|
||||
type: integer
|
||||
format: uint32
|
||||
minimum: 0
|
||||
AssetOwner:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
DisplayName:
|
||||
type: string
|
||||
maxLength: 128
|
||||
Creator:
|
||||
type: string
|
||||
maxLength: 128
|
||||
GameID:
|
||||
type: integer
|
||||
format: uint32
|
||||
minimum: 0
|
||||
AssetID:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
AssetVersion:
|
||||
type: integer
|
||||
format: uint64
|
||||
minimum: 0
|
||||
Script:
|
||||
required:
|
||||
- ID
|
||||
@@ -310,7 +648,8 @@ components:
|
||||
properties:
|
||||
ID:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
Name:
|
||||
type: string
|
||||
maxLength: 128
|
||||
@@ -323,10 +662,12 @@ components:
|
||||
maxLength: 1048576
|
||||
ResourceType:
|
||||
type: integer
|
||||
format: int32
|
||||
format: uint32
|
||||
minimum: 0
|
||||
ResourceID:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
ScriptCreate:
|
||||
required:
|
||||
- Name
|
||||
@@ -343,10 +684,12 @@ components:
|
||||
maxLength: 1048576
|
||||
ResourceType:
|
||||
type: integer
|
||||
format: int32
|
||||
format: uint32
|
||||
minimum: 0
|
||||
ResourceID:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
ScriptPolicy:
|
||||
required:
|
||||
- ID
|
||||
@@ -357,17 +700,20 @@ components:
|
||||
properties:
|
||||
ID:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
FromScriptHash:
|
||||
type: string
|
||||
minLength: 16
|
||||
maxLength: 16
|
||||
ToScriptID:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
Policy:
|
||||
type: integer
|
||||
format: int32
|
||||
format: uint32
|
||||
minimum: 0
|
||||
ScriptPolicyCreate:
|
||||
required:
|
||||
- FromScriptID
|
||||
@@ -377,20 +723,24 @@ components:
|
||||
properties:
|
||||
FromScriptID:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
ToScriptID:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
Policy:
|
||||
type: integer
|
||||
format: int32
|
||||
format: uint32
|
||||
minimum: 0
|
||||
Error:
|
||||
description: Represents error object
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
format: int64
|
||||
format: uint64
|
||||
minimum: 0
|
||||
message:
|
||||
type: string
|
||||
required:
|
||||
|
||||
1021
openapi.yaml
1021
openapi.yaml
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -6,31 +6,54 @@ package api
|
||||
type OperationName = string
|
||||
|
||||
const (
|
||||
ActionMapfixAcceptedOperation OperationName = "ActionMapfixAccepted"
|
||||
ActionMapfixRejectOperation OperationName = "ActionMapfixReject"
|
||||
ActionMapfixRequestChangesOperation OperationName = "ActionMapfixRequestChanges"
|
||||
ActionMapfixResetSubmittingOperation OperationName = "ActionMapfixResetSubmitting"
|
||||
ActionMapfixRetryValidateOperation OperationName = "ActionMapfixRetryValidate"
|
||||
ActionMapfixRevokeOperation OperationName = "ActionMapfixRevoke"
|
||||
ActionMapfixTriggerSubmitOperation OperationName = "ActionMapfixTriggerSubmit"
|
||||
ActionMapfixTriggerUploadOperation OperationName = "ActionMapfixTriggerUpload"
|
||||
ActionMapfixTriggerValidateOperation OperationName = "ActionMapfixTriggerValidate"
|
||||
ActionMapfixValidatedOperation OperationName = "ActionMapfixValidated"
|
||||
ActionSubmissionAcceptedOperation OperationName = "ActionSubmissionAccepted"
|
||||
ActionSubmissionRejectOperation OperationName = "ActionSubmissionReject"
|
||||
ActionSubmissionRequestChangesOperation OperationName = "ActionSubmissionRequestChanges"
|
||||
ActionSubmissionResetSubmittingOperation OperationName = "ActionSubmissionResetSubmitting"
|
||||
ActionSubmissionRetryValidateOperation OperationName = "ActionSubmissionRetryValidate"
|
||||
ActionSubmissionRevokeOperation OperationName = "ActionSubmissionRevoke"
|
||||
ActionSubmissionSubmitOperation OperationName = "ActionSubmissionSubmit"
|
||||
ActionSubmissionTriggerSubmitOperation OperationName = "ActionSubmissionTriggerSubmit"
|
||||
ActionSubmissionTriggerUploadOperation OperationName = "ActionSubmissionTriggerUpload"
|
||||
ActionSubmissionTriggerValidateOperation OperationName = "ActionSubmissionTriggerValidate"
|
||||
ActionSubmissionValidatedOperation OperationName = "ActionSubmissionValidated"
|
||||
CreateMapfixOperation OperationName = "CreateMapfix"
|
||||
CreateMapfixAuditCommentOperation OperationName = "CreateMapfixAuditComment"
|
||||
CreateScriptOperation OperationName = "CreateScript"
|
||||
CreateScriptPolicyOperation OperationName = "CreateScriptPolicy"
|
||||
CreateSubmissionOperation OperationName = "CreateSubmission"
|
||||
CreateSubmissionAuditCommentOperation OperationName = "CreateSubmissionAuditComment"
|
||||
DeleteScriptOperation OperationName = "DeleteScript"
|
||||
DeleteScriptPolicyOperation OperationName = "DeleteScriptPolicy"
|
||||
GetMapOperation OperationName = "GetMap"
|
||||
GetMapfixOperation OperationName = "GetMapfix"
|
||||
GetOperationOperation OperationName = "GetOperation"
|
||||
GetScriptOperation OperationName = "GetScript"
|
||||
GetScriptPolicyOperation OperationName = "GetScriptPolicy"
|
||||
GetSubmissionOperation OperationName = "GetSubmission"
|
||||
ListMapfixAuditEventsOperation OperationName = "ListMapfixAuditEvents"
|
||||
ListMapfixesOperation OperationName = "ListMapfixes"
|
||||
ListMapsOperation OperationName = "ListMaps"
|
||||
ListScriptPolicyOperation OperationName = "ListScriptPolicy"
|
||||
ListScriptsOperation OperationName = "ListScripts"
|
||||
ListSubmissionAuditEventsOperation OperationName = "ListSubmissionAuditEvents"
|
||||
ListSubmissionsOperation OperationName = "ListSubmissions"
|
||||
ReleaseSubmissionsOperation OperationName = "ReleaseSubmissions"
|
||||
SessionRolesOperation OperationName = "SessionRoles"
|
||||
SessionUserOperation OperationName = "SessionUser"
|
||||
SessionValidateOperation OperationName = "SessionValidate"
|
||||
SetMapfixCompletedOperation OperationName = "SetMapfixCompleted"
|
||||
SetSubmissionCompletedOperation OperationName = "SetSubmissionCompleted"
|
||||
UpdateMapfixModelOperation OperationName = "UpdateMapfixModel"
|
||||
UpdateScriptOperation OperationName = "UpdateScript"
|
||||
UpdateScriptPolicyOperation OperationName = "UpdateScriptPolicy"
|
||||
UpdateSubmissionModelOperation OperationName = "UpdateSubmissionModel"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
@@ -15,6 +16,111 @@ import (
|
||||
"github.com/ogen-go/ogen/validate"
|
||||
)
|
||||
|
||||
func (s *Server) decodeCreateMapfixRequest(r *http.Request) (
|
||||
req *MapfixTriggerCreate,
|
||||
close func() error,
|
||||
rerr error,
|
||||
) {
|
||||
var closers []func() error
|
||||
close = func() error {
|
||||
var merr error
|
||||
// Close in reverse order, to match defer behavior.
|
||||
for i := len(closers) - 1; i >= 0; i-- {
|
||||
c := closers[i]
|
||||
merr = multierr.Append(merr, c())
|
||||
}
|
||||
return merr
|
||||
}
|
||||
defer func() {
|
||||
if rerr != nil {
|
||||
rerr = multierr.Append(rerr, close())
|
||||
}
|
||||
}()
|
||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
return req, close, errors.Wrap(err, "parse media type")
|
||||
}
|
||||
switch {
|
||||
case ct == "application/json":
|
||||
if r.ContentLength == 0 {
|
||||
return req, close, validate.ErrBodyRequired
|
||||
}
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return req, close, err
|
||||
}
|
||||
|
||||
if len(buf) == 0 {
|
||||
return req, close, validate.ErrBodyRequired
|
||||
}
|
||||
|
||||
d := jx.DecodeBytes(buf)
|
||||
|
||||
var request MapfixTriggerCreate
|
||||
if err := func() error {
|
||||
if err := request.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 req, close, err
|
||||
}
|
||||
if err := func() error {
|
||||
if err := request.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return req, close, errors.Wrap(err, "validate")
|
||||
}
|
||||
return &request, close, nil
|
||||
default:
|
||||
return req, close, validate.InvalidContentType(ct)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) decodeCreateMapfixAuditCommentRequest(r *http.Request) (
|
||||
req CreateMapfixAuditCommentReq,
|
||||
close func() error,
|
||||
rerr error,
|
||||
) {
|
||||
var closers []func() error
|
||||
close = func() error {
|
||||
var merr error
|
||||
// Close in reverse order, to match defer behavior.
|
||||
for i := len(closers) - 1; i >= 0; i-- {
|
||||
c := closers[i]
|
||||
merr = multierr.Append(merr, c())
|
||||
}
|
||||
return merr
|
||||
}
|
||||
defer func() {
|
||||
if rerr != nil {
|
||||
rerr = multierr.Append(rerr, close())
|
||||
}
|
||||
}()
|
||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
return req, close, errors.Wrap(err, "parse media type")
|
||||
}
|
||||
switch {
|
||||
case ct == "text/plain":
|
||||
reader := r.Body
|
||||
request := CreateMapfixAuditCommentReq{Data: reader}
|
||||
return request, close, nil
|
||||
default:
|
||||
return req, close, validate.InvalidContentType(ct)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) decodeCreateScriptRequest(r *http.Request) (
|
||||
req *ScriptCreate,
|
||||
close func() error,
|
||||
@@ -143,6 +249,14 @@ func (s *Server) decodeCreateScriptPolicyRequest(r *http.Request) (
|
||||
}
|
||||
return req, close, err
|
||||
}
|
||||
if err := func() error {
|
||||
if err := request.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return req, close, errors.Wrap(err, "validate")
|
||||
}
|
||||
return &request, close, nil
|
||||
default:
|
||||
return req, close, validate.InvalidContentType(ct)
|
||||
@@ -150,7 +264,7 @@ func (s *Server) decodeCreateScriptPolicyRequest(r *http.Request) (
|
||||
}
|
||||
|
||||
func (s *Server) decodeCreateSubmissionRequest(r *http.Request) (
|
||||
req *SubmissionCreate,
|
||||
req *SubmissionTriggerCreate,
|
||||
close func() error,
|
||||
rerr error,
|
||||
) {
|
||||
@@ -189,7 +303,7 @@ func (s *Server) decodeCreateSubmissionRequest(r *http.Request) (
|
||||
|
||||
d := jx.DecodeBytes(buf)
|
||||
|
||||
var request SubmissionCreate
|
||||
var request SubmissionTriggerCreate
|
||||
if err := func() error {
|
||||
if err := request.Decode(d); err != nil {
|
||||
return err
|
||||
@@ -220,6 +334,40 @@ func (s *Server) decodeCreateSubmissionRequest(r *http.Request) (
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) decodeCreateSubmissionAuditCommentRequest(r *http.Request) (
|
||||
req CreateSubmissionAuditCommentReq,
|
||||
close func() error,
|
||||
rerr error,
|
||||
) {
|
||||
var closers []func() error
|
||||
close = func() error {
|
||||
var merr error
|
||||
// Close in reverse order, to match defer behavior.
|
||||
for i := len(closers) - 1; i >= 0; i-- {
|
||||
c := closers[i]
|
||||
merr = multierr.Append(merr, c())
|
||||
}
|
||||
return merr
|
||||
}
|
||||
defer func() {
|
||||
if rerr != nil {
|
||||
rerr = multierr.Append(rerr, close())
|
||||
}
|
||||
}()
|
||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
return req, close, errors.Wrap(err, "parse media type")
|
||||
}
|
||||
switch {
|
||||
case ct == "text/plain":
|
||||
reader := r.Body
|
||||
request := CreateSubmissionAuditCommentReq{Data: reader}
|
||||
return request, close, nil
|
||||
default:
|
||||
return req, close, validate.InvalidContentType(ct)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) decodeReleaseSubmissionsRequest(r *http.Request) (
|
||||
req []ReleaseInfo,
|
||||
close func() error,
|
||||
@@ -297,6 +445,23 @@ func (s *Server) decodeReleaseSubmissionsRequest(r *http.Request) (
|
||||
}).ValidateLength(len(request)); err != nil {
|
||||
return errors.Wrap(err, "array")
|
||||
}
|
||||
var failures []validate.FieldError
|
||||
for i, elem := range request {
|
||||
if err := func() error {
|
||||
if err := elem.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: fmt.Sprintf("[%d]", i),
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return req, close, errors.Wrap(err, "validate")
|
||||
@@ -435,6 +600,14 @@ func (s *Server) decodeUpdateScriptPolicyRequest(r *http.Request) (
|
||||
}
|
||||
return req, close, err
|
||||
}
|
||||
if err := func() error {
|
||||
if err := request.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return req, close, errors.Wrap(err, "validate")
|
||||
}
|
||||
return &request, close, nil
|
||||
default:
|
||||
return req, close, validate.InvalidContentType(ct)
|
||||
|
||||
@@ -11,6 +11,30 @@ import (
|
||||
ht "github.com/ogen-go/ogen/http"
|
||||
)
|
||||
|
||||
func encodeCreateMapfixRequest(
|
||||
req *MapfixTriggerCreate,
|
||||
r *http.Request,
|
||||
) error {
|
||||
const contentType = "application/json"
|
||||
e := new(jx.Encoder)
|
||||
{
|
||||
req.Encode(e)
|
||||
}
|
||||
encoded := e.Bytes()
|
||||
ht.SetBody(r, bytes.NewReader(encoded), contentType)
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateMapfixAuditCommentRequest(
|
||||
req CreateMapfixAuditCommentReq,
|
||||
r *http.Request,
|
||||
) error {
|
||||
const contentType = "text/plain"
|
||||
body := req
|
||||
ht.SetBody(r, body, contentType)
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateScriptRequest(
|
||||
req *ScriptCreate,
|
||||
r *http.Request,
|
||||
@@ -40,7 +64,7 @@ func encodeCreateScriptPolicyRequest(
|
||||
}
|
||||
|
||||
func encodeCreateSubmissionRequest(
|
||||
req *SubmissionCreate,
|
||||
req *SubmissionTriggerCreate,
|
||||
r *http.Request,
|
||||
) error {
|
||||
const contentType = "application/json"
|
||||
@@ -53,6 +77,16 @@ func encodeCreateSubmissionRequest(
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateSubmissionAuditCommentRequest(
|
||||
req CreateSubmissionAuditCommentReq,
|
||||
r *http.Request,
|
||||
) error {
|
||||
const contentType = "text/plain"
|
||||
body := req
|
||||
ht.SetBody(r, body, contentType)
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeReleaseSubmissionsRequest(
|
||||
req []ReleaseInfo,
|
||||
r *http.Request,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,76 @@ import (
|
||||
ht "github.com/ogen-go/ogen/http"
|
||||
)
|
||||
|
||||
func encodeActionMapfixAcceptedResponse(response *ActionMapfixAcceptedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionMapfixRejectResponse(response *ActionMapfixRejectNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionMapfixRequestChangesResponse(response *ActionMapfixRequestChangesNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionMapfixResetSubmittingResponse(response *ActionMapfixResetSubmittingNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionMapfixRetryValidateResponse(response *ActionMapfixRetryValidateNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionMapfixRevokeResponse(response *ActionMapfixRevokeNoContent, 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))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionMapfixTriggerUploadResponse(response *ActionMapfixTriggerUploadNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionMapfixTriggerValidateResponse(response *ActionMapfixTriggerValidateNoContent, 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))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionSubmissionAcceptedResponse(response *ActionSubmissionAcceptedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
@@ -34,6 +104,13 @@ func encodeActionSubmissionRequestChangesResponse(response *ActionSubmissionRequ
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionSubmissionResetSubmittingResponse(response *ActionSubmissionResetSubmittingNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionSubmissionRetryValidateResponse(response *ActionSubmissionRetryValidateNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
@@ -48,7 +125,7 @@ func encodeActionSubmissionRevokeResponse(response *ActionSubmissionRevokeNoCont
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionSubmissionSubmitResponse(response *ActionSubmissionSubmitNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
func encodeActionSubmissionTriggerSubmitResponse(response *ActionSubmissionTriggerSubmitNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
@@ -76,7 +153,7 @@ func encodeActionSubmissionValidatedResponse(response *ActionSubmissionValidated
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateScriptResponse(response *ID, w http.ResponseWriter, span trace.Span) error {
|
||||
func encodeCreateMapfixResponse(response *OperationID, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(201)
|
||||
span.SetStatus(codes.Ok, http.StatusText(201))
|
||||
@@ -90,7 +167,14 @@ func encodeCreateScriptResponse(response *ID, w http.ResponseWriter, span trace.
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateScriptPolicyResponse(response *ID, w http.ResponseWriter, span trace.Span) error {
|
||||
func encodeCreateMapfixAuditCommentResponse(response *CreateMapfixAuditCommentNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateScriptResponse(response *ScriptID, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(201)
|
||||
span.SetStatus(codes.Ok, http.StatusText(201))
|
||||
@@ -104,7 +188,7 @@ func encodeCreateScriptPolicyResponse(response *ID, w http.ResponseWriter, span
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateSubmissionResponse(response *ID, w http.ResponseWriter, span trace.Span) error {
|
||||
func encodeCreateScriptPolicyResponse(response *ScriptPolicyID, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(201)
|
||||
span.SetStatus(codes.Ok, http.StatusText(201))
|
||||
@@ -118,6 +202,27 @@ func encodeCreateSubmissionResponse(response *ID, w http.ResponseWriter, span tr
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateSubmissionResponse(response *OperationID, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(201)
|
||||
span.SetStatus(codes.Ok, http.StatusText(201))
|
||||
|
||||
e := new(jx.Encoder)
|
||||
response.Encode(e)
|
||||
if _, err := e.WriteTo(w); err != nil {
|
||||
return errors.Wrap(err, "write")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateSubmissionAuditCommentResponse(response *CreateSubmissionAuditCommentNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeDeleteScriptResponse(response *DeleteScriptNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
@@ -132,6 +237,48 @@ func encodeDeleteScriptPolicyResponse(response *DeleteScriptPolicyNoContent, w h
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeGetMapResponse(response *Map, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(200)
|
||||
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||
|
||||
e := new(jx.Encoder)
|
||||
response.Encode(e)
|
||||
if _, err := e.WriteTo(w); err != nil {
|
||||
return errors.Wrap(err, "write")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeGetMapfixResponse(response *Mapfix, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(200)
|
||||
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||
|
||||
e := new(jx.Encoder)
|
||||
response.Encode(e)
|
||||
if _, err := e.WriteTo(w); err != nil {
|
||||
return errors.Wrap(err, "write")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeGetOperationResponse(response *Operation, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(200)
|
||||
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||
|
||||
e := new(jx.Encoder)
|
||||
response.Encode(e)
|
||||
if _, err := e.WriteTo(w); err != nil {
|
||||
return errors.Wrap(err, "write")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeGetScriptResponse(response *Script, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(200)
|
||||
@@ -174,6 +321,56 @@ func encodeGetSubmissionResponse(response *Submission, w http.ResponseWriter, sp
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeListMapfixAuditEventsResponse(response []AuditEvent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(200)
|
||||
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||
|
||||
e := new(jx.Encoder)
|
||||
e.ArrStart()
|
||||
for _, elem := range response {
|
||||
elem.Encode(e)
|
||||
}
|
||||
e.ArrEnd()
|
||||
if _, err := e.WriteTo(w); err != nil {
|
||||
return errors.Wrap(err, "write")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeListMapfixesResponse(response *Mapfixes, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(200)
|
||||
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||
|
||||
e := new(jx.Encoder)
|
||||
response.Encode(e)
|
||||
if _, err := e.WriteTo(w); err != nil {
|
||||
return errors.Wrap(err, "write")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeListMapsResponse(response []Map, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(200)
|
||||
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||
|
||||
e := new(jx.Encoder)
|
||||
e.ArrStart()
|
||||
for _, elem := range response {
|
||||
elem.Encode(e)
|
||||
}
|
||||
e.ArrEnd()
|
||||
if _, err := e.WriteTo(w); err != nil {
|
||||
return errors.Wrap(err, "write")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeListScriptPolicyResponse(response []ScriptPolicy, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(200)
|
||||
@@ -210,7 +407,7 @@ func encodeListScriptsResponse(response []Script, w http.ResponseWriter, span tr
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeListSubmissionsResponse(response []Submission, w http.ResponseWriter, span trace.Span) error {
|
||||
func encodeListSubmissionAuditEventsResponse(response []AuditEvent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(200)
|
||||
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||
@@ -228,6 +425,20 @@ func encodeListSubmissionsResponse(response []Submission, w http.ResponseWriter,
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeListSubmissionsResponse(response *Submissions, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(200)
|
||||
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||
|
||||
e := new(jx.Encoder)
|
||||
response.Encode(e)
|
||||
if _, err := e.WriteTo(w); err != nil {
|
||||
return errors.Wrap(err, "write")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeReleaseSubmissionsResponse(response *ReleaseSubmissionsCreated, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(201)
|
||||
span.SetStatus(codes.Ok, http.StatusText(201))
|
||||
@@ -277,6 +488,13 @@ func encodeSessionValidateResponse(response bool, w http.ResponseWriter, span tr
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeSetMapfixCompletedResponse(response *SetMapfixCompletedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeSetSubmissionCompletedResponse(response *SetSubmissionCompletedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
@@ -284,6 +502,13 @@ func encodeSetSubmissionCompletedResponse(response *SetSubmissionCompletedNoCont
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeUpdateMapfixModelResponse(response *UpdateMapfixModelNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeUpdateScriptResponse(response *UpdateScriptNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,67 @@ import (
|
||||
|
||||
// Handler handles operations described by OpenAPI v3 specification.
|
||||
type Handler interface {
|
||||
// ActionMapfixAccepted implements actionMapfixAccepted operation.
|
||||
//
|
||||
// Role Reviewer manually resets validating softlock and changes status from Validating -> Accepted.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-validating
|
||||
ActionMapfixAccepted(ctx context.Context, params ActionMapfixAcceptedParams) error
|
||||
// ActionMapfixReject implements actionMapfixReject operation.
|
||||
//
|
||||
// Role Reviewer changes status from Submitted -> Rejected.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reject
|
||||
ActionMapfixReject(ctx context.Context, params ActionMapfixRejectParams) error
|
||||
// ActionMapfixRequestChanges implements actionMapfixRequestChanges operation.
|
||||
//
|
||||
// Role Reviewer changes status from Validated|Accepted|Submitted -> ChangesRequested.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/request-changes
|
||||
ActionMapfixRequestChanges(ctx context.Context, params ActionMapfixRequestChangesParams) error
|
||||
// ActionMapfixResetSubmitting implements actionMapfixResetSubmitting operation.
|
||||
//
|
||||
// Role Submitter manually resets submitting softlock and changes status from Submitting ->
|
||||
// UnderConstruction.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-submitting
|
||||
ActionMapfixResetSubmitting(ctx context.Context, params ActionMapfixResetSubmittingParams) error
|
||||
// ActionMapfixRetryValidate implements actionMapfixRetryValidate operation.
|
||||
//
|
||||
// Role Reviewer re-runs validation and changes status from Accepted -> Validating.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/retry-validate
|
||||
ActionMapfixRetryValidate(ctx context.Context, params ActionMapfixRetryValidateParams) error
|
||||
// ActionMapfixRevoke implements actionMapfixRevoke operation.
|
||||
//
|
||||
// Role Submitter changes status from Submitted|ChangesRequested -> UnderConstruction.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/revoke
|
||||
ActionMapfixRevoke(ctx context.Context, params ActionMapfixRevokeParams) error
|
||||
// ActionMapfixTriggerSubmit implements actionMapfixTriggerSubmit operation.
|
||||
//
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-submit
|
||||
ActionMapfixTriggerSubmit(ctx context.Context, params ActionMapfixTriggerSubmitParams) error
|
||||
// ActionMapfixTriggerUpload implements actionMapfixTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-upload
|
||||
ActionMapfixTriggerUpload(ctx context.Context, params ActionMapfixTriggerUploadParams) error
|
||||
// ActionMapfixTriggerValidate implements actionMapfixTriggerValidate operation.
|
||||
//
|
||||
// Role Reviewer triggers validation and changes status from Submitted -> Validating.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-validate
|
||||
ActionMapfixTriggerValidate(ctx context.Context, params ActionMapfixTriggerValidateParams) error
|
||||
// ActionMapfixValidated implements actionMapfixValidated operation.
|
||||
//
|
||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-uploading
|
||||
ActionMapfixValidated(ctx context.Context, params ActionMapfixValidatedParams) error
|
||||
// ActionSubmissionAccepted implements actionSubmissionAccepted operation.
|
||||
//
|
||||
// Role Reviewer manually resets validating softlock and changes status from Validating -> Accepted.
|
||||
@@ -26,6 +87,13 @@ type Handler interface {
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/request-changes
|
||||
ActionSubmissionRequestChanges(ctx context.Context, params ActionSubmissionRequestChangesParams) error
|
||||
// ActionSubmissionResetSubmitting implements actionSubmissionResetSubmitting operation.
|
||||
//
|
||||
// Role Submitter manually resets submitting softlock and changes status from Submitting ->
|
||||
// UnderConstruction.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/reset-submitting
|
||||
ActionSubmissionResetSubmitting(ctx context.Context, params ActionSubmissionResetSubmittingParams) error
|
||||
// ActionSubmissionRetryValidate implements actionSubmissionRetryValidate operation.
|
||||
//
|
||||
// Role Reviewer re-runs validation and changes status from Accepted -> Validating.
|
||||
@@ -38,12 +106,12 @@ type Handler interface {
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/revoke
|
||||
ActionSubmissionRevoke(ctx context.Context, params ActionSubmissionRevokeParams) error
|
||||
// ActionSubmissionSubmit implements actionSubmissionSubmit operation.
|
||||
// ActionSubmissionTriggerSubmit implements actionSubmissionTriggerSubmit operation.
|
||||
//
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitted.
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/submit
|
||||
ActionSubmissionSubmit(ctx context.Context, params ActionSubmissionSubmitParams) error
|
||||
// POST /submissions/{SubmissionID}/status/trigger-submit
|
||||
ActionSubmissionTriggerSubmit(ctx context.Context, params ActionSubmissionTriggerSubmitParams) error
|
||||
// ActionSubmissionTriggerUpload implements actionSubmissionTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
@@ -62,24 +130,42 @@ type Handler interface {
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/reset-uploading
|
||||
ActionSubmissionValidated(ctx context.Context, params ActionSubmissionValidatedParams) error
|
||||
// CreateMapfix implements createMapfix operation.
|
||||
//
|
||||
// Trigger the validator to create a mapfix.
|
||||
//
|
||||
// POST /mapfixes
|
||||
CreateMapfix(ctx context.Context, req *MapfixTriggerCreate) (*OperationID, error)
|
||||
// CreateMapfixAuditComment implements createMapfixAuditComment operation.
|
||||
//
|
||||
// Post a comment to the audit log.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/comment
|
||||
CreateMapfixAuditComment(ctx context.Context, req CreateMapfixAuditCommentReq, params CreateMapfixAuditCommentParams) error
|
||||
// CreateScript implements createScript operation.
|
||||
//
|
||||
// Create a new script.
|
||||
//
|
||||
// POST /scripts
|
||||
CreateScript(ctx context.Context, req *ScriptCreate) (*ID, error)
|
||||
CreateScript(ctx context.Context, req *ScriptCreate) (*ScriptID, error)
|
||||
// CreateScriptPolicy implements createScriptPolicy operation.
|
||||
//
|
||||
// Create a new script policy.
|
||||
//
|
||||
// POST /script-policy
|
||||
CreateScriptPolicy(ctx context.Context, req *ScriptPolicyCreate) (*ID, error)
|
||||
CreateScriptPolicy(ctx context.Context, req *ScriptPolicyCreate) (*ScriptPolicyID, error)
|
||||
// CreateSubmission implements createSubmission operation.
|
||||
//
|
||||
// Create new submission.
|
||||
// Trigger the validator to create a new submission.
|
||||
//
|
||||
// POST /submissions
|
||||
CreateSubmission(ctx context.Context, req *SubmissionCreate) (*ID, error)
|
||||
CreateSubmission(ctx context.Context, req *SubmissionTriggerCreate) (*OperationID, error)
|
||||
// CreateSubmissionAuditComment implements createSubmissionAuditComment operation.
|
||||
//
|
||||
// Post a comment to the audit log.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/comment
|
||||
CreateSubmissionAuditComment(ctx context.Context, req CreateSubmissionAuditCommentReq, params CreateSubmissionAuditCommentParams) error
|
||||
// DeleteScript implements deleteScript operation.
|
||||
//
|
||||
// Delete the specified script by ID.
|
||||
@@ -92,6 +178,24 @@ type Handler interface {
|
||||
//
|
||||
// DELETE /script-policy/{ScriptPolicyID}
|
||||
DeleteScriptPolicy(ctx context.Context, params DeleteScriptPolicyParams) error
|
||||
// GetMap implements getMap operation.
|
||||
//
|
||||
// Retrieve map with ID.
|
||||
//
|
||||
// GET /maps/{MapID}
|
||||
GetMap(ctx context.Context, params GetMapParams) (*Map, error)
|
||||
// GetMapfix implements getMapfix operation.
|
||||
//
|
||||
// Retrieve map with ID.
|
||||
//
|
||||
// GET /mapfixes/{MapfixID}
|
||||
GetMapfix(ctx context.Context, params GetMapfixParams) (*Mapfix, error)
|
||||
// GetOperation implements getOperation operation.
|
||||
//
|
||||
// Retrieve operation with ID.
|
||||
//
|
||||
// GET /operations/{OperationID}
|
||||
GetOperation(ctx context.Context, params GetOperationParams) (*Operation, error)
|
||||
// GetScript implements getScript operation.
|
||||
//
|
||||
// Get the specified script by ID.
|
||||
@@ -110,6 +214,24 @@ type Handler interface {
|
||||
//
|
||||
// GET /submissions/{SubmissionID}
|
||||
GetSubmission(ctx context.Context, params GetSubmissionParams) (*Submission, error)
|
||||
// ListMapfixAuditEvents implements listMapfixAuditEvents operation.
|
||||
//
|
||||
// Retrieve a list of audit events.
|
||||
//
|
||||
// GET /mapfixes/{MapfixID}/audit-events
|
||||
ListMapfixAuditEvents(ctx context.Context, params ListMapfixAuditEventsParams) ([]AuditEvent, error)
|
||||
// ListMapfixes implements listMapfixes operation.
|
||||
//
|
||||
// Get list of mapfixes.
|
||||
//
|
||||
// GET /mapfixes
|
||||
ListMapfixes(ctx context.Context, params ListMapfixesParams) (*Mapfixes, error)
|
||||
// ListMaps implements listMaps operation.
|
||||
//
|
||||
// Get list of maps.
|
||||
//
|
||||
// GET /maps
|
||||
ListMaps(ctx context.Context, params ListMapsParams) ([]Map, error)
|
||||
// ListScriptPolicy implements listScriptPolicy operation.
|
||||
//
|
||||
// Get list of script policies.
|
||||
@@ -122,12 +244,18 @@ type Handler interface {
|
||||
//
|
||||
// GET /scripts
|
||||
ListScripts(ctx context.Context, params ListScriptsParams) ([]Script, error)
|
||||
// ListSubmissionAuditEvents implements listSubmissionAuditEvents operation.
|
||||
//
|
||||
// Retrieve a list of audit events.
|
||||
//
|
||||
// GET /submissions/{SubmissionID}/audit-events
|
||||
ListSubmissionAuditEvents(ctx context.Context, params ListSubmissionAuditEventsParams) ([]AuditEvent, error)
|
||||
// ListSubmissions implements listSubmissions operation.
|
||||
//
|
||||
// Get list of submissions.
|
||||
//
|
||||
// GET /submissions
|
||||
ListSubmissions(ctx context.Context, params ListSubmissionsParams) ([]Submission, error)
|
||||
ListSubmissions(ctx context.Context, params ListSubmissionsParams) (*Submissions, error)
|
||||
// ReleaseSubmissions implements releaseSubmissions operation.
|
||||
//
|
||||
// Release a set of uploaded maps.
|
||||
@@ -152,12 +280,24 @@ type Handler interface {
|
||||
//
|
||||
// GET /session/validate
|
||||
SessionValidate(ctx context.Context) (bool, error)
|
||||
// SetMapfixCompleted implements setMapfixCompleted operation.
|
||||
//
|
||||
// Called by maptest when a player completes the map.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/completed
|
||||
SetMapfixCompleted(ctx context.Context, params SetMapfixCompletedParams) error
|
||||
// SetSubmissionCompleted implements setSubmissionCompleted operation.
|
||||
//
|
||||
// Called by maptest when a player completes the map.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/completed
|
||||
SetSubmissionCompleted(ctx context.Context, params SetSubmissionCompletedParams) error
|
||||
// UpdateMapfixModel implements updateMapfixModel operation.
|
||||
//
|
||||
// Update model following role restrictions.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/model
|
||||
UpdateMapfixModel(ctx context.Context, params UpdateMapfixModelParams) error
|
||||
// UpdateScript implements updateScript operation.
|
||||
//
|
||||
// Update the specified script by ID.
|
||||
|
||||
@@ -13,6 +13,97 @@ type UnimplementedHandler struct{}
|
||||
|
||||
var _ Handler = UnimplementedHandler{}
|
||||
|
||||
// ActionMapfixAccepted implements actionMapfixAccepted operation.
|
||||
//
|
||||
// Role Reviewer manually resets validating softlock and changes status from Validating -> Accepted.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-validating
|
||||
func (UnimplementedHandler) ActionMapfixAccepted(ctx context.Context, params ActionMapfixAcceptedParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixReject implements actionMapfixReject operation.
|
||||
//
|
||||
// Role Reviewer changes status from Submitted -> Rejected.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reject
|
||||
func (UnimplementedHandler) ActionMapfixReject(ctx context.Context, params ActionMapfixRejectParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixRequestChanges implements actionMapfixRequestChanges operation.
|
||||
//
|
||||
// Role Reviewer changes status from Validated|Accepted|Submitted -> ChangesRequested.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/request-changes
|
||||
func (UnimplementedHandler) ActionMapfixRequestChanges(ctx context.Context, params ActionMapfixRequestChangesParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixResetSubmitting implements actionMapfixResetSubmitting operation.
|
||||
//
|
||||
// Role Submitter manually resets submitting softlock and changes status from Submitting ->
|
||||
// UnderConstruction.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-submitting
|
||||
func (UnimplementedHandler) ActionMapfixResetSubmitting(ctx context.Context, params ActionMapfixResetSubmittingParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixRetryValidate implements actionMapfixRetryValidate operation.
|
||||
//
|
||||
// Role Reviewer re-runs validation and changes status from Accepted -> Validating.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/retry-validate
|
||||
func (UnimplementedHandler) ActionMapfixRetryValidate(ctx context.Context, params ActionMapfixRetryValidateParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixRevoke implements actionMapfixRevoke operation.
|
||||
//
|
||||
// Role Submitter changes status from Submitted|ChangesRequested -> UnderConstruction.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/revoke
|
||||
func (UnimplementedHandler) ActionMapfixRevoke(ctx context.Context, params ActionMapfixRevokeParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerSubmit implements actionMapfixTriggerSubmit operation.
|
||||
//
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-submit
|
||||
func (UnimplementedHandler) ActionMapfixTriggerSubmit(ctx context.Context, params ActionMapfixTriggerSubmitParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerUpload implements actionMapfixTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-upload
|
||||
func (UnimplementedHandler) ActionMapfixTriggerUpload(ctx context.Context, params ActionMapfixTriggerUploadParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerValidate implements actionMapfixTriggerValidate operation.
|
||||
//
|
||||
// Role Reviewer triggers validation and changes status from Submitted -> Validating.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-validate
|
||||
func (UnimplementedHandler) ActionMapfixTriggerValidate(ctx context.Context, params ActionMapfixTriggerValidateParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixValidated implements actionMapfixValidated operation.
|
||||
//
|
||||
// Role Admin 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 {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionSubmissionAccepted implements actionSubmissionAccepted operation.
|
||||
//
|
||||
// Role Reviewer manually resets validating softlock and changes status from Validating -> Accepted.
|
||||
@@ -40,6 +131,16 @@ func (UnimplementedHandler) ActionSubmissionRequestChanges(ctx context.Context,
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionSubmissionResetSubmitting implements actionSubmissionResetSubmitting operation.
|
||||
//
|
||||
// Role Submitter manually resets submitting softlock and changes status from Submitting ->
|
||||
// UnderConstruction.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/reset-submitting
|
||||
func (UnimplementedHandler) ActionSubmissionResetSubmitting(ctx context.Context, params ActionSubmissionResetSubmittingParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionSubmissionRetryValidate implements actionSubmissionRetryValidate operation.
|
||||
//
|
||||
// Role Reviewer re-runs validation and changes status from Accepted -> Validating.
|
||||
@@ -58,12 +159,12 @@ func (UnimplementedHandler) ActionSubmissionRevoke(ctx context.Context, params A
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionSubmissionSubmit implements actionSubmissionSubmit operation.
|
||||
// ActionSubmissionTriggerSubmit implements actionSubmissionTriggerSubmit operation.
|
||||
//
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitted.
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/submit
|
||||
func (UnimplementedHandler) ActionSubmissionSubmit(ctx context.Context, params ActionSubmissionSubmitParams) error {
|
||||
// POST /submissions/{SubmissionID}/status/trigger-submit
|
||||
func (UnimplementedHandler) ActionSubmissionTriggerSubmit(ctx context.Context, params ActionSubmissionTriggerSubmitParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
@@ -94,12 +195,30 @@ func (UnimplementedHandler) ActionSubmissionValidated(ctx context.Context, param
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// CreateMapfix implements createMapfix operation.
|
||||
//
|
||||
// Trigger the validator to create a mapfix.
|
||||
//
|
||||
// POST /mapfixes
|
||||
func (UnimplementedHandler) CreateMapfix(ctx context.Context, req *MapfixTriggerCreate) (r *OperationID, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// CreateMapfixAuditComment implements createMapfixAuditComment operation.
|
||||
//
|
||||
// Post a comment to the audit log.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/comment
|
||||
func (UnimplementedHandler) CreateMapfixAuditComment(ctx context.Context, req CreateMapfixAuditCommentReq, params CreateMapfixAuditCommentParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// CreateScript implements createScript operation.
|
||||
//
|
||||
// Create a new script.
|
||||
//
|
||||
// POST /scripts
|
||||
func (UnimplementedHandler) CreateScript(ctx context.Context, req *ScriptCreate) (r *ID, _ error) {
|
||||
func (UnimplementedHandler) CreateScript(ctx context.Context, req *ScriptCreate) (r *ScriptID, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
@@ -108,19 +227,28 @@ func (UnimplementedHandler) CreateScript(ctx context.Context, req *ScriptCreate)
|
||||
// Create a new script policy.
|
||||
//
|
||||
// POST /script-policy
|
||||
func (UnimplementedHandler) CreateScriptPolicy(ctx context.Context, req *ScriptPolicyCreate) (r *ID, _ error) {
|
||||
func (UnimplementedHandler) CreateScriptPolicy(ctx context.Context, req *ScriptPolicyCreate) (r *ScriptPolicyID, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// CreateSubmission implements createSubmission operation.
|
||||
//
|
||||
// Create new submission.
|
||||
// Trigger the validator to create a new submission.
|
||||
//
|
||||
// POST /submissions
|
||||
func (UnimplementedHandler) CreateSubmission(ctx context.Context, req *SubmissionCreate) (r *ID, _ error) {
|
||||
func (UnimplementedHandler) CreateSubmission(ctx context.Context, req *SubmissionTriggerCreate) (r *OperationID, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// CreateSubmissionAuditComment implements createSubmissionAuditComment operation.
|
||||
//
|
||||
// Post a comment to the audit log.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/comment
|
||||
func (UnimplementedHandler) CreateSubmissionAuditComment(ctx context.Context, req CreateSubmissionAuditCommentReq, params CreateSubmissionAuditCommentParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// DeleteScript implements deleteScript operation.
|
||||
//
|
||||
// Delete the specified script by ID.
|
||||
@@ -139,6 +267,33 @@ func (UnimplementedHandler) DeleteScriptPolicy(ctx context.Context, params Delet
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// GetMap implements getMap operation.
|
||||
//
|
||||
// Retrieve map with ID.
|
||||
//
|
||||
// GET /maps/{MapID}
|
||||
func (UnimplementedHandler) GetMap(ctx context.Context, params GetMapParams) (r *Map, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// GetMapfix implements getMapfix operation.
|
||||
//
|
||||
// Retrieve map with ID.
|
||||
//
|
||||
// GET /mapfixes/{MapfixID}
|
||||
func (UnimplementedHandler) GetMapfix(ctx context.Context, params GetMapfixParams) (r *Mapfix, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// GetOperation implements getOperation operation.
|
||||
//
|
||||
// Retrieve operation with ID.
|
||||
//
|
||||
// GET /operations/{OperationID}
|
||||
func (UnimplementedHandler) GetOperation(ctx context.Context, params GetOperationParams) (r *Operation, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// GetScript implements getScript operation.
|
||||
//
|
||||
// Get the specified script by ID.
|
||||
@@ -166,6 +321,33 @@ func (UnimplementedHandler) GetSubmission(ctx context.Context, params GetSubmiss
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ListMapfixAuditEvents implements listMapfixAuditEvents operation.
|
||||
//
|
||||
// Retrieve a list of audit events.
|
||||
//
|
||||
// GET /mapfixes/{MapfixID}/audit-events
|
||||
func (UnimplementedHandler) ListMapfixAuditEvents(ctx context.Context, params ListMapfixAuditEventsParams) (r []AuditEvent, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ListMapfixes implements listMapfixes operation.
|
||||
//
|
||||
// Get list of mapfixes.
|
||||
//
|
||||
// GET /mapfixes
|
||||
func (UnimplementedHandler) ListMapfixes(ctx context.Context, params ListMapfixesParams) (r *Mapfixes, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ListMaps implements listMaps operation.
|
||||
//
|
||||
// Get list of maps.
|
||||
//
|
||||
// GET /maps
|
||||
func (UnimplementedHandler) ListMaps(ctx context.Context, params ListMapsParams) (r []Map, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ListScriptPolicy implements listScriptPolicy operation.
|
||||
//
|
||||
// Get list of script policies.
|
||||
@@ -184,12 +366,21 @@ func (UnimplementedHandler) ListScripts(ctx context.Context, params ListScriptsP
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ListSubmissionAuditEvents implements listSubmissionAuditEvents operation.
|
||||
//
|
||||
// Retrieve a list of audit events.
|
||||
//
|
||||
// GET /submissions/{SubmissionID}/audit-events
|
||||
func (UnimplementedHandler) ListSubmissionAuditEvents(ctx context.Context, params ListSubmissionAuditEventsParams) (r []AuditEvent, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ListSubmissions implements listSubmissions operation.
|
||||
//
|
||||
// Get list of submissions.
|
||||
//
|
||||
// GET /submissions
|
||||
func (UnimplementedHandler) ListSubmissions(ctx context.Context, params ListSubmissionsParams) (r []Submission, _ error) {
|
||||
func (UnimplementedHandler) ListSubmissions(ctx context.Context, params ListSubmissionsParams) (r *Submissions, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
@@ -229,6 +420,15 @@ func (UnimplementedHandler) SessionValidate(ctx context.Context) (r bool, _ erro
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// SetMapfixCompleted implements setMapfixCompleted operation.
|
||||
//
|
||||
// Called by maptest when a player completes the map.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/completed
|
||||
func (UnimplementedHandler) SetMapfixCompleted(ctx context.Context, params SetMapfixCompletedParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// SetSubmissionCompleted implements setSubmissionCompleted operation.
|
||||
//
|
||||
// Called by maptest when a player completes the map.
|
||||
@@ -238,6 +438,15 @@ func (UnimplementedHandler) SetSubmissionCompleted(ctx context.Context, params S
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// UpdateMapfixModel implements updateMapfixModel operation.
|
||||
//
|
||||
// Update model following role restrictions.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/model
|
||||
func (UnimplementedHandler) UpdateMapfixModel(ctx context.Context, params UpdateMapfixModelParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// UpdateScript implements updateScript operation.
|
||||
//
|
||||
// Update the specified script by ID.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,8 @@ package datastore
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
@@ -22,11 +24,42 @@ const (
|
||||
)
|
||||
|
||||
type Datastore interface {
|
||||
AuditEvents() AuditEvents
|
||||
Mapfixes() Mapfixes
|
||||
Operations() Operations
|
||||
Submissions() Submissions
|
||||
Scripts() Scripts
|
||||
ScriptPolicy() ScriptPolicy
|
||||
}
|
||||
|
||||
type AuditEvents interface {
|
||||
Get(ctx context.Context, id int64) (model.AuditEvent, error)
|
||||
Create(ctx context.Context, smap model.AuditEvent) (model.AuditEvent, error)
|
||||
Update(ctx context.Context, id int64, values OptionalMap) error
|
||||
Delete(ctx context.Context, id int64) error
|
||||
List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.AuditEvent, error)
|
||||
}
|
||||
|
||||
type Mapfixes interface {
|
||||
Get(ctx context.Context, id int64) (model.Mapfix, error)
|
||||
GetList(ctx context.Context, id []int64) ([]model.Mapfix, error)
|
||||
Create(ctx context.Context, smap model.Mapfix) (model.Mapfix, error)
|
||||
Update(ctx context.Context, id int64, values OptionalMap) error
|
||||
IfStatusThenUpdate(ctx context.Context, id int64, statuses []model.MapfixStatus, values OptionalMap) error
|
||||
IfStatusThenUpdateAndGet(ctx context.Context, id int64, statuses []model.MapfixStatus, values OptionalMap) (model.Mapfix, error)
|
||||
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) (uint64, []model.Mapfix, error)
|
||||
}
|
||||
|
||||
type Operations interface {
|
||||
Get(ctx context.Context, id int32) (model.Operation, error)
|
||||
Create(ctx context.Context, smap model.Operation) (model.Operation, error)
|
||||
Update(ctx context.Context, id int32, values OptionalMap) error
|
||||
Delete(ctx context.Context, id int32) error
|
||||
CountSince(ctx context.Context, owner int64, since time.Time) (int64, error)
|
||||
}
|
||||
|
||||
type Submissions interface {
|
||||
Get(ctx context.Context, id int64) (model.Submission, error)
|
||||
GetList(ctx context.Context, id []int64) ([]model.Submission, error)
|
||||
@@ -36,6 +69,7 @@ type Submissions interface {
|
||||
IfStatusThenUpdateAndGet(ctx context.Context, id int64, statuses []model.SubmissionStatus, values OptionalMap) (model.Submission, error)
|
||||
Delete(ctx context.Context, id int64) error
|
||||
List(ctx context.Context, filters OptionalMap, page model.Page, sort ListSort) ([]model.Submission, error)
|
||||
ListWithTotal(ctx context.Context, filters OptionalMap, page model.Page, sort ListSort) (int64, []model.Submission, error)
|
||||
}
|
||||
|
||||
type Scripts interface {
|
||||
|
||||
@@ -10,7 +10,17 @@ func Optional() OptionalMap {
|
||||
return OptionalMap{filter: map[string]interface{}{}}
|
||||
}
|
||||
|
||||
func (q OptionalMap) Add(column string, value interface{}) OptionalMap {
|
||||
func (q OptionalMap) Add2(column string, value interface{}) OptionalMap {
|
||||
q.filter[column] = value
|
||||
return q
|
||||
}
|
||||
|
||||
func (q OptionalMap) AddPostgresInt32(column string, value uint32) OptionalMap {
|
||||
q.filter[column] = value
|
||||
return q
|
||||
}
|
||||
|
||||
func (q OptionalMap) AddPostgresInt64(column string, value uint64) OptionalMap {
|
||||
q.filter[column] = value
|
||||
return q
|
||||
}
|
||||
|
||||
64
pkg/datastore/gormstore/audit_events.go
Normal file
64
pkg/datastore/gormstore/audit_events.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package gormstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type AuditEvents struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (env *AuditEvents) Get(ctx context.Context, id int64) (model.AuditEvent, error) {
|
||||
var mdl model.AuditEvent
|
||||
if err := env.db.First(&mdl, id).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return mdl, datastore.ErrNotExist
|
||||
}
|
||||
return mdl, err
|
||||
}
|
||||
return mdl, nil
|
||||
}
|
||||
|
||||
func (env *AuditEvents) Create(ctx context.Context, smap model.AuditEvent) (model.AuditEvent, error) {
|
||||
if err := env.db.Create(&smap).Error; err != nil {
|
||||
return smap, err
|
||||
}
|
||||
|
||||
return smap, nil
|
||||
}
|
||||
|
||||
func (env *AuditEvents) Update(ctx context.Context, id int64, values datastore.OptionalMap) error {
|
||||
if err := env.db.Model(&model.AuditEvent{}).Where("id = ?", id).Updates(values.Map()).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return datastore.ErrNotExist
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (env *AuditEvents) Delete(ctx context.Context, id int64) error {
|
||||
if err := env.db.Delete(&model.AuditEvent{}, id).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return datastore.ErrNotExist
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (env *AuditEvents) List(ctx context.Context, filters datastore.OptionalMap, page model.Page) ([]model.AuditEvent, error) {
|
||||
var events []model.AuditEvent
|
||||
if err := env.db.Where(filters.Map()).Offset(int((page.Number - 1) * page.Size)).Limit(int(page.Size)).Find(&events).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return events, nil
|
||||
}
|
||||
@@ -31,6 +31,9 @@ func New(ctx *cli.Context) (datastore.Datastore, error) {
|
||||
|
||||
if ctx.Bool("migrate") {
|
||||
if err := db.AutoMigrate(
|
||||
&model.AuditEvent{},
|
||||
&model.Mapfix{},
|
||||
&model.Operation{},
|
||||
&model.Submission{},
|
||||
&model.Script{},
|
||||
&model.ScriptPolicy{},
|
||||
|
||||
@@ -9,6 +9,18 @@ type Gormstore struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (g Gormstore) AuditEvents() datastore.AuditEvents {
|
||||
return &AuditEvents{db: g.db}
|
||||
}
|
||||
|
||||
func (g Gormstore) Mapfixes() datastore.Mapfixes {
|
||||
return &Mapfixes{db: g.db}
|
||||
}
|
||||
|
||||
func (g Gormstore) Operations() datastore.Operations {
|
||||
return &Operations{db: g.db}
|
||||
}
|
||||
|
||||
func (g Gormstore) Submissions() datastore.Submissions {
|
||||
return &Submissions{db: g.db}
|
||||
}
|
||||
|
||||
148
pkg/datastore/gormstore/mapfixes.go
Normal file
148
pkg/datastore/gormstore/mapfixes.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package gormstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
type Mapfixes struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (env *Mapfixes) Get(ctx context.Context, id int64) (model.Mapfix, error) {
|
||||
var mapfix model.Mapfix
|
||||
if err := env.db.First(&mapfix, id).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return mapfix, datastore.ErrNotExist
|
||||
}
|
||||
return mapfix, err
|
||||
}
|
||||
return mapfix, nil
|
||||
}
|
||||
|
||||
func (env *Mapfixes) GetList(ctx context.Context, id []int64) ([]model.Mapfix, error) {
|
||||
var mapList []model.Mapfix
|
||||
if err := env.db.Find(&mapList, "id IN ?", id).Error; err != nil {
|
||||
return mapList, err
|
||||
}
|
||||
|
||||
return mapList, nil
|
||||
}
|
||||
|
||||
func (env *Mapfixes) Create(ctx context.Context, smap model.Mapfix) (model.Mapfix, error) {
|
||||
if err := env.db.Create(&smap).Error; err != nil {
|
||||
return smap, err
|
||||
}
|
||||
|
||||
return smap, nil
|
||||
}
|
||||
|
||||
func (env *Mapfixes) Update(ctx context.Context, id int64, values datastore.OptionalMap) error {
|
||||
if err := env.db.Model(&model.Mapfix{}).Where("id = ?", id).Updates(values.Map()).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return datastore.ErrNotExist
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// the update can only occur if the status matches one of the provided values.
|
||||
func (env *Mapfixes) IfStatusThenUpdate(ctx context.Context, id int64, statuses []model.MapfixStatus, values datastore.OptionalMap) error {
|
||||
if err := env.db.Model(&model.Mapfix{}).Where("id = ?", id).Where("status_id IN ?", statuses).Updates(values.Map()).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return datastore.ErrNotExist
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// the update can only occur if the status matches one of the provided values.
|
||||
// returns the updated value
|
||||
func (env *Mapfixes) IfStatusThenUpdateAndGet(ctx context.Context, id int64, statuses []model.MapfixStatus, values datastore.OptionalMap) (model.Mapfix, error) {
|
||||
var mapfix model.Mapfix
|
||||
result := env.db.Model(&mapfix).
|
||||
Clauses(clause.Returning{}).
|
||||
Where("id = ?", id).
|
||||
Where("status_id IN ?", statuses).
|
||||
Updates(values.Map())
|
||||
if result.Error != nil {
|
||||
if result.Error == gorm.ErrRecordNotFound {
|
||||
return mapfix, datastore.ErrNotExist
|
||||
}
|
||||
return mapfix, result.Error
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return mapfix, datastore.ErroNoRowsAffected
|
||||
}
|
||||
|
||||
return mapfix, nil
|
||||
}
|
||||
|
||||
func (env *Mapfixes) Delete(ctx context.Context, id int64) error {
|
||||
if err := env.db.Delete(&model.Mapfix{}, id).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return datastore.ErrNotExist
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (env *Mapfixes) List(ctx context.Context, filters datastore.OptionalMap, page model.Page, sort datastore.ListSort) ([]model.Mapfix, error) {
|
||||
var maps []model.Mapfix
|
||||
|
||||
db := env.db
|
||||
|
||||
switch sort {
|
||||
case datastore.ListSortDisabled:
|
||||
// No sort
|
||||
break
|
||||
case datastore.ListSortDisplayNameAscending:
|
||||
db=db.Order("display_name ASC")
|
||||
break
|
||||
case datastore.ListSortDisplayNameDescending:
|
||||
db=db.Order("display_name DESC")
|
||||
break
|
||||
case datastore.ListSortDateAscending:
|
||||
db=db.Order("created_at ASC")
|
||||
break
|
||||
case datastore.ListSortDateDescending:
|
||||
db=db.Order("created_at DESC")
|
||||
break
|
||||
default:
|
||||
return nil, datastore.ErrInvalidListSort
|
||||
}
|
||||
|
||||
if err := db.Where(filters.Map()).Offset(int((page.Number - 1) * page.Size)).Limit(int(page.Size)).Find(&maps).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return maps, nil
|
||||
}
|
||||
|
||||
func (env *Mapfixes) ListWithTotal(ctx context.Context, filters datastore.OptionalMap, page model.Page, sort datastore.ListSort) (uint64, []model.Mapfix, error) {
|
||||
// grab page items
|
||||
maps, err := env.List(ctx, filters, page, sort)
|
||||
if err != nil{
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
// count total with filters
|
||||
var total int64
|
||||
if err := env.db.Model(&model.Mapfix{}).Where(filters.Map()).Count(&total).Error; err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
return uint64(total), maps, nil
|
||||
}
|
||||
65
pkg/datastore/gormstore/operations.go
Normal file
65
pkg/datastore/gormstore/operations.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package gormstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Operations struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (env *Operations) Get(ctx context.Context, id int32) (model.Operation, error) {
|
||||
var operation model.Operation
|
||||
if err := env.db.First(&operation, id).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return operation, datastore.ErrNotExist
|
||||
}
|
||||
return operation, err
|
||||
}
|
||||
return operation, nil
|
||||
}
|
||||
|
||||
func (env *Operations) Create(ctx context.Context, smap model.Operation) (model.Operation, error) {
|
||||
if err := env.db.Create(&smap).Error; err != nil {
|
||||
return smap, err
|
||||
}
|
||||
|
||||
return smap, nil
|
||||
}
|
||||
|
||||
func (env *Operations) Update(ctx context.Context, id int32, values datastore.OptionalMap) error {
|
||||
if err := env.db.Model(&model.Operation{}).Where("id = ?", id).Updates(values.Map()).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return datastore.ErrNotExist
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (env *Operations) Delete(ctx context.Context, id int32) error {
|
||||
if err := env.db.Delete(&model.Operation{}, id).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return datastore.ErrNotExist
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (env *Operations) CountSince(ctx context.Context, owner int64, since time.Time) (int64, error) {
|
||||
var count int64
|
||||
if err := env.db.Model(&model.Operation{}).Where("owner = ? AND created_at > ?",owner,since).Count(&count).Error; err != nil {
|
||||
return count, err
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
@@ -130,3 +130,19 @@ func (env *Submissions) List(ctx context.Context, filters datastore.OptionalMap,
|
||||
|
||||
return maps, nil
|
||||
}
|
||||
|
||||
func (env *Submissions) ListWithTotal(ctx context.Context, filters datastore.OptionalMap, page model.Page, sort datastore.ListSort) (int64, []model.Submission, error) {
|
||||
// grab page items
|
||||
maps, err := env.List(ctx, filters, page, sort)
|
||||
if err != nil{
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
// count total with filters
|
||||
var total int64
|
||||
if err := env.db.Model(&model.Submission{}).Where(filters.Map()).Count(&total).Error; err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
return total, maps, nil
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -6,13 +6,22 @@ package api
|
||||
type OperationName = string
|
||||
|
||||
const (
|
||||
ActionMapfixAcceptedOperation OperationName = "ActionMapfixAccepted"
|
||||
ActionMapfixSubmittedOperation OperationName = "ActionMapfixSubmitted"
|
||||
ActionMapfixUploadedOperation OperationName = "ActionMapfixUploaded"
|
||||
ActionMapfixValidatedOperation OperationName = "ActionMapfixValidated"
|
||||
ActionOperationFailedOperation OperationName = "ActionOperationFailed"
|
||||
ActionSubmissionAcceptedOperation OperationName = "ActionSubmissionAccepted"
|
||||
ActionSubmissionSubmittedOperation OperationName = "ActionSubmissionSubmitted"
|
||||
ActionSubmissionUploadedOperation OperationName = "ActionSubmissionUploaded"
|
||||
ActionSubmissionValidatedOperation OperationName = "ActionSubmissionValidated"
|
||||
CreateMapfixOperation OperationName = "CreateMapfix"
|
||||
CreateScriptOperation OperationName = "CreateScript"
|
||||
CreateScriptPolicyOperation OperationName = "CreateScriptPolicy"
|
||||
CreateSubmissionOperation OperationName = "CreateSubmission"
|
||||
GetScriptOperation OperationName = "GetScript"
|
||||
ListScriptPolicyOperation OperationName = "ListScriptPolicy"
|
||||
ListScriptsOperation OperationName = "ListScripts"
|
||||
UpdateMapfixValidatedModelOperation OperationName = "UpdateMapfixValidatedModel"
|
||||
UpdateSubmissionValidatedModelOperation OperationName = "UpdateSubmissionValidatedModel"
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,77 @@ import (
|
||||
"github.com/ogen-go/ogen/validate"
|
||||
)
|
||||
|
||||
func (s *Server) decodeCreateMapfixRequest(r *http.Request) (
|
||||
req *MapfixCreate,
|
||||
close func() error,
|
||||
rerr error,
|
||||
) {
|
||||
var closers []func() error
|
||||
close = func() error {
|
||||
var merr error
|
||||
// Close in reverse order, to match defer behavior.
|
||||
for i := len(closers) - 1; i >= 0; i-- {
|
||||
c := closers[i]
|
||||
merr = multierr.Append(merr, c())
|
||||
}
|
||||
return merr
|
||||
}
|
||||
defer func() {
|
||||
if rerr != nil {
|
||||
rerr = multierr.Append(rerr, close())
|
||||
}
|
||||
}()
|
||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
return req, close, errors.Wrap(err, "parse media type")
|
||||
}
|
||||
switch {
|
||||
case ct == "application/json":
|
||||
if r.ContentLength == 0 {
|
||||
return req, close, validate.ErrBodyRequired
|
||||
}
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return req, close, err
|
||||
}
|
||||
|
||||
if len(buf) == 0 {
|
||||
return req, close, validate.ErrBodyRequired
|
||||
}
|
||||
|
||||
d := jx.DecodeBytes(buf)
|
||||
|
||||
var request MapfixCreate
|
||||
if err := func() error {
|
||||
if err := request.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 req, close, err
|
||||
}
|
||||
if err := func() error {
|
||||
if err := request.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return req, close, errors.Wrap(err, "validate")
|
||||
}
|
||||
return &request, close, nil
|
||||
default:
|
||||
return req, close, validate.InvalidContentType(ct)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) decodeCreateScriptRequest(r *http.Request) (
|
||||
req *ScriptCreate,
|
||||
close func() error,
|
||||
@@ -143,6 +214,85 @@ func (s *Server) decodeCreateScriptPolicyRequest(r *http.Request) (
|
||||
}
|
||||
return req, close, err
|
||||
}
|
||||
if err := func() error {
|
||||
if err := request.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return req, close, errors.Wrap(err, "validate")
|
||||
}
|
||||
return &request, close, nil
|
||||
default:
|
||||
return req, close, validate.InvalidContentType(ct)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) decodeCreateSubmissionRequest(r *http.Request) (
|
||||
req *SubmissionCreate,
|
||||
close func() error,
|
||||
rerr error,
|
||||
) {
|
||||
var closers []func() error
|
||||
close = func() error {
|
||||
var merr error
|
||||
// Close in reverse order, to match defer behavior.
|
||||
for i := len(closers) - 1; i >= 0; i-- {
|
||||
c := closers[i]
|
||||
merr = multierr.Append(merr, c())
|
||||
}
|
||||
return merr
|
||||
}
|
||||
defer func() {
|
||||
if rerr != nil {
|
||||
rerr = multierr.Append(rerr, close())
|
||||
}
|
||||
}()
|
||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
return req, close, errors.Wrap(err, "parse media type")
|
||||
}
|
||||
switch {
|
||||
case ct == "application/json":
|
||||
if r.ContentLength == 0 {
|
||||
return req, close, validate.ErrBodyRequired
|
||||
}
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return req, close, err
|
||||
}
|
||||
|
||||
if len(buf) == 0 {
|
||||
return req, close, validate.ErrBodyRequired
|
||||
}
|
||||
|
||||
d := jx.DecodeBytes(buf)
|
||||
|
||||
var request SubmissionCreate
|
||||
if err := func() error {
|
||||
if err := request.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 req, close, err
|
||||
}
|
||||
if err := func() error {
|
||||
if err := request.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return req, close, errors.Wrap(err, "validate")
|
||||
}
|
||||
return &request, close, nil
|
||||
default:
|
||||
return req, close, validate.InvalidContentType(ct)
|
||||
|
||||
@@ -11,6 +11,20 @@ import (
|
||||
ht "github.com/ogen-go/ogen/http"
|
||||
)
|
||||
|
||||
func encodeCreateMapfixRequest(
|
||||
req *MapfixCreate,
|
||||
r *http.Request,
|
||||
) error {
|
||||
const contentType = "application/json"
|
||||
e := new(jx.Encoder)
|
||||
{
|
||||
req.Encode(e)
|
||||
}
|
||||
encoded := e.Bytes()
|
||||
ht.SetBody(r, bytes.NewReader(encoded), contentType)
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateScriptRequest(
|
||||
req *ScriptCreate,
|
||||
r *http.Request,
|
||||
@@ -38,3 +52,17 @@ func encodeCreateScriptPolicyRequest(
|
||||
ht.SetBody(r, bytes.NewReader(encoded), contentType)
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateSubmissionRequest(
|
||||
req *SubmissionCreate,
|
||||
r *http.Request,
|
||||
) error {
|
||||
const contentType = "application/json"
|
||||
e := new(jx.Encoder)
|
||||
{
|
||||
req.Encode(e)
|
||||
}
|
||||
encoded := e.Bytes()
|
||||
ht.SetBody(r, bytes.NewReader(encoded), contentType)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -15,6 +15,306 @@ import (
|
||||
"github.com/ogen-go/ogen/validate"
|
||||
)
|
||||
|
||||
func decodeActionMapfixAcceptedResponse(resp *http.Response) (res *ActionMapfixAcceptedNoContent, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 204:
|
||||
// Code 204.
|
||||
return &ActionMapfixAcceptedNoContent{}, 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 decodeActionMapfixSubmittedResponse(resp *http.Response) (res *ActionMapfixSubmittedNoContent, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 204:
|
||||
// Code 204.
|
||||
return &ActionMapfixSubmittedNoContent{}, 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 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:
|
||||
// Code 204.
|
||||
return &ActionMapfixValidatedNoContent{}, 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 decodeActionOperationFailedResponse(resp *http.Response) (res *ActionOperationFailedNoContent, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 204:
|
||||
// Code 204.
|
||||
return &ActionOperationFailedNoContent{}, 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 decodeActionSubmissionAcceptedResponse(resp *http.Response) (res *ActionSubmissionAcceptedNoContent, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 204:
|
||||
@@ -52,6 +352,75 @@ func decodeActionSubmissionAcceptedResponse(resp *http.Response) (res *ActionSub
|
||||
}
|
||||
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 decodeActionSubmissionSubmittedResponse(resp *http.Response) (res *ActionSubmissionSubmittedNoContent, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 204:
|
||||
// Code 204.
|
||||
return &ActionSubmissionSubmittedNoContent{}, 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,
|
||||
@@ -103,6 +472,15 @@ func decodeActionSubmissionUploadedResponse(resp *http.Response) (res *ActionSub
|
||||
}
|
||||
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,
|
||||
@@ -154,6 +532,15 @@ func decodeActionSubmissionValidatedResponse(resp *http.Response) (res *ActionSu
|
||||
}
|
||||
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,
|
||||
@@ -168,7 +555,7 @@ func decodeActionSubmissionValidatedResponse(resp *http.Response) (res *ActionSu
|
||||
return res, errors.Wrap(defRes, "error")
|
||||
}
|
||||
|
||||
func decodeCreateScriptResponse(resp *http.Response) (res *ID, _ error) {
|
||||
func decodeCreateMapfixResponse(resp *http.Response) (res *MapfixID, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 201:
|
||||
// Code 201.
|
||||
@@ -184,7 +571,7 @@ func decodeCreateScriptResponse(resp *http.Response) (res *ID, _ error) {
|
||||
}
|
||||
d := jx.DecodeBytes(buf)
|
||||
|
||||
var response ID
|
||||
var response MapfixID
|
||||
if err := func() error {
|
||||
if err := response.Decode(d); err != nil {
|
||||
return err
|
||||
@@ -201,6 +588,15 @@ func decodeCreateScriptResponse(resp *http.Response) (res *ID, _ error) {
|
||||
}
|
||||
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 &response, nil
|
||||
default:
|
||||
return res, validate.InvalidContentType(ct)
|
||||
@@ -237,6 +633,15 @@ func decodeCreateScriptResponse(resp *http.Response) (res *ID, _ error) {
|
||||
}
|
||||
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,
|
||||
@@ -251,7 +656,7 @@ func decodeCreateScriptResponse(resp *http.Response) (res *ID, _ error) {
|
||||
return res, errors.Wrap(defRes, "error")
|
||||
}
|
||||
|
||||
func decodeCreateScriptPolicyResponse(resp *http.Response) (res *ID, _ error) {
|
||||
func decodeCreateScriptResponse(resp *http.Response) (res *ScriptID, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 201:
|
||||
// Code 201.
|
||||
@@ -267,7 +672,7 @@ func decodeCreateScriptPolicyResponse(resp *http.Response) (res *ID, _ error) {
|
||||
}
|
||||
d := jx.DecodeBytes(buf)
|
||||
|
||||
var response ID
|
||||
var response ScriptID
|
||||
if err := func() error {
|
||||
if err := response.Decode(d); err != nil {
|
||||
return err
|
||||
@@ -284,6 +689,15 @@ func decodeCreateScriptPolicyResponse(resp *http.Response) (res *ID, _ error) {
|
||||
}
|
||||
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 &response, nil
|
||||
default:
|
||||
return res, validate.InvalidContentType(ct)
|
||||
@@ -320,6 +734,217 @@ func decodeCreateScriptPolicyResponse(resp *http.Response) (res *ID, _ error) {
|
||||
}
|
||||
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 decodeCreateScriptPolicyResponse(resp *http.Response) (res *ScriptPolicyID, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 201:
|
||||
// Code 201.
|
||||
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 ScriptPolicyID
|
||||
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 &response, nil
|
||||
default:
|
||||
return res, validate.InvalidContentType(ct)
|
||||
}
|
||||
}
|
||||
// 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 decodeCreateSubmissionResponse(resp *http.Response) (res *SubmissionID, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 201:
|
||||
// Code 201.
|
||||
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 SubmissionID
|
||||
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 &response, nil
|
||||
default:
|
||||
return res, validate.InvalidContentType(ct)
|
||||
}
|
||||
}
|
||||
// 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,
|
||||
@@ -412,6 +1037,15 @@ func decodeGetScriptResponse(resp *http.Response) (res *Script, _ error) {
|
||||
}
|
||||
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,
|
||||
@@ -529,6 +1163,15 @@ func decodeListScriptPolicyResponse(resp *http.Response) (res []ScriptPolicy, _
|
||||
}
|
||||
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,
|
||||
@@ -646,6 +1289,75 @@ func decodeListScriptsResponse(resp *http.Response) (res []Script, _ error) {
|
||||
}
|
||||
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 decodeUpdateMapfixValidatedModelResponse(resp *http.Response) (res *UpdateMapfixValidatedModelNoContent, _ error) {
|
||||
switch resp.StatusCode {
|
||||
case 204:
|
||||
// Code 204.
|
||||
return &UpdateMapfixValidatedModelNoContent{}, 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,
|
||||
@@ -697,6 +1409,15 @@ func decodeUpdateSubmissionValidatedModelResponse(resp *http.Response) (res *Upd
|
||||
}
|
||||
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,
|
||||
|
||||
@@ -13,6 +13,41 @@ import (
|
||||
ht "github.com/ogen-go/ogen/http"
|
||||
)
|
||||
|
||||
func encodeActionMapfixAcceptedResponse(response *ActionMapfixAcceptedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionMapfixSubmittedResponse(response *ActionMapfixSubmittedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
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))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionOperationFailedResponse(response *ActionOperationFailedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionSubmissionAcceptedResponse(response *ActionSubmissionAcceptedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
@@ -20,6 +55,13 @@ func encodeActionSubmissionAcceptedResponse(response *ActionSubmissionAcceptedNo
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionSubmissionSubmittedResponse(response *ActionSubmissionSubmittedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeActionSubmissionUploadedResponse(response *ActionSubmissionUploadedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
@@ -34,7 +76,7 @@ func encodeActionSubmissionValidatedResponse(response *ActionSubmissionValidated
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateScriptResponse(response *ID, w http.ResponseWriter, span trace.Span) error {
|
||||
func encodeCreateMapfixResponse(response *MapfixID, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(201)
|
||||
span.SetStatus(codes.Ok, http.StatusText(201))
|
||||
@@ -48,7 +90,35 @@ func encodeCreateScriptResponse(response *ID, w http.ResponseWriter, span trace.
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateScriptPolicyResponse(response *ID, w http.ResponseWriter, span trace.Span) error {
|
||||
func encodeCreateScriptResponse(response *ScriptID, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(201)
|
||||
span.SetStatus(codes.Ok, http.StatusText(201))
|
||||
|
||||
e := new(jx.Encoder)
|
||||
response.Encode(e)
|
||||
if _, err := e.WriteTo(w); err != nil {
|
||||
return errors.Wrap(err, "write")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateScriptPolicyResponse(response *ScriptPolicyID, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(201)
|
||||
span.SetStatus(codes.Ok, http.StatusText(201))
|
||||
|
||||
e := new(jx.Encoder)
|
||||
response.Encode(e)
|
||||
if _, err := e.WriteTo(w); err != nil {
|
||||
return errors.Wrap(err, "write")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeCreateSubmissionResponse(response *SubmissionID, w http.ResponseWriter, span trace.Span) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(201)
|
||||
span.SetStatus(codes.Ok, http.StatusText(201))
|
||||
@@ -112,6 +182,13 @@ func encodeListScriptsResponse(response []Script, w http.ResponseWriter, span tr
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeUpdateMapfixValidatedModelResponse(response *UpdateMapfixValidatedModelNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeUpdateSubmissionValidatedModelResponse(response *UpdateSubmissionValidatedModelNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||
w.WriteHeader(204)
|
||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,9 +10,27 @@ func (s *ErrorStatusCode) Error() string {
|
||||
return fmt.Sprintf("code %d: %+v", s.StatusCode, s.Response)
|
||||
}
|
||||
|
||||
// ActionMapfixAcceptedNoContent is response for ActionMapfixAccepted operation.
|
||||
type ActionMapfixAcceptedNoContent struct{}
|
||||
|
||||
// ActionMapfixSubmittedNoContent is response for ActionMapfixSubmitted operation.
|
||||
type ActionMapfixSubmittedNoContent struct{}
|
||||
|
||||
// ActionMapfixUploadedNoContent is response for ActionMapfixUploaded operation.
|
||||
type ActionMapfixUploadedNoContent struct{}
|
||||
|
||||
// ActionMapfixValidatedNoContent is response for ActionMapfixValidated operation.
|
||||
type ActionMapfixValidatedNoContent struct{}
|
||||
|
||||
// ActionOperationFailedNoContent is response for ActionOperationFailed operation.
|
||||
type ActionOperationFailedNoContent struct{}
|
||||
|
||||
// ActionSubmissionAcceptedNoContent is response for ActionSubmissionAccepted operation.
|
||||
type ActionSubmissionAcceptedNoContent struct{}
|
||||
|
||||
// ActionSubmissionSubmittedNoContent is response for ActionSubmissionSubmitted operation.
|
||||
type ActionSubmissionSubmittedNoContent struct{}
|
||||
|
||||
// ActionSubmissionUploadedNoContent is response for ActionSubmissionUploaded operation.
|
||||
type ActionSubmissionUploadedNoContent struct{}
|
||||
|
||||
@@ -22,12 +40,12 @@ type ActionSubmissionValidatedNoContent struct{}
|
||||
// Represents error object.
|
||||
// Ref: #/components/schemas/Error
|
||||
type Error struct {
|
||||
Code int64 `json:"code"`
|
||||
Code uint64 `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// GetCode returns the value of Code.
|
||||
func (s *Error) GetCode() int64 {
|
||||
func (s *Error) GetCode() uint64 {
|
||||
return s.Code
|
||||
}
|
||||
|
||||
@@ -37,7 +55,7 @@ func (s *Error) GetMessage() string {
|
||||
}
|
||||
|
||||
// SetCode sets the value of Code.
|
||||
func (s *Error) SetCode(val int64) {
|
||||
func (s *Error) SetCode(val uint64) {
|
||||
s.Code = val
|
||||
}
|
||||
|
||||
@@ -72,111 +90,111 @@ func (s *ErrorStatusCode) SetResponse(val Error) {
|
||||
s.Response = val
|
||||
}
|
||||
|
||||
// Ref: #/components/schemas/Id
|
||||
type ID struct {
|
||||
ID int64 `json:"ID"`
|
||||
// Ref: #/components/schemas/MapfixCreate
|
||||
type MapfixCreate struct {
|
||||
OperationID uint32 `json:"OperationID"`
|
||||
AssetOwner uint64 `json:"AssetOwner"`
|
||||
DisplayName string `json:"DisplayName"`
|
||||
Creator string `json:"Creator"`
|
||||
GameID uint32 `json:"GameID"`
|
||||
AssetID uint64 `json:"AssetID"`
|
||||
AssetVersion uint64 `json:"AssetVersion"`
|
||||
TargetAssetID uint64 `json:"TargetAssetID"`
|
||||
}
|
||||
|
||||
// GetID returns the value of ID.
|
||||
func (s *ID) GetID() int64 {
|
||||
return s.ID
|
||||
// GetOperationID returns the value of OperationID.
|
||||
func (s *MapfixCreate) GetOperationID() uint32 {
|
||||
return s.OperationID
|
||||
}
|
||||
|
||||
// SetID sets the value of ID.
|
||||
func (s *ID) SetID(val int64) {
|
||||
s.ID = val
|
||||
// GetAssetOwner returns the value of AssetOwner.
|
||||
func (s *MapfixCreate) GetAssetOwner() uint64 {
|
||||
return s.AssetOwner
|
||||
}
|
||||
|
||||
// NewOptInt32 returns new OptInt32 with value set to v.
|
||||
func NewOptInt32(v int32) OptInt32 {
|
||||
return OptInt32{
|
||||
Value: v,
|
||||
Set: true,
|
||||
}
|
||||
// GetDisplayName returns the value of DisplayName.
|
||||
func (s *MapfixCreate) GetDisplayName() string {
|
||||
return s.DisplayName
|
||||
}
|
||||
|
||||
// OptInt32 is optional int32.
|
||||
type OptInt32 struct {
|
||||
Value int32
|
||||
Set bool
|
||||
// GetCreator returns the value of Creator.
|
||||
func (s *MapfixCreate) GetCreator() string {
|
||||
return s.Creator
|
||||
}
|
||||
|
||||
// IsSet returns true if OptInt32 was set.
|
||||
func (o OptInt32) IsSet() bool { return o.Set }
|
||||
|
||||
// Reset unsets value.
|
||||
func (o *OptInt32) Reset() {
|
||||
var v int32
|
||||
o.Value = v
|
||||
o.Set = false
|
||||
// GetGameID returns the value of GameID.
|
||||
func (s *MapfixCreate) GetGameID() uint32 {
|
||||
return s.GameID
|
||||
}
|
||||
|
||||
// SetTo sets value to v.
|
||||
func (o *OptInt32) SetTo(v int32) {
|
||||
o.Set = true
|
||||
o.Value = v
|
||||
// GetAssetID returns the value of AssetID.
|
||||
func (s *MapfixCreate) GetAssetID() uint64 {
|
||||
return s.AssetID
|
||||
}
|
||||
|
||||
// Get returns value and boolean that denotes whether value was set.
|
||||
func (o OptInt32) Get() (v int32, ok bool) {
|
||||
if !o.Set {
|
||||
return v, false
|
||||
}
|
||||
return o.Value, true
|
||||
// GetAssetVersion returns the value of AssetVersion.
|
||||
func (s *MapfixCreate) GetAssetVersion() uint64 {
|
||||
return s.AssetVersion
|
||||
}
|
||||
|
||||
// Or returns value if set, or given parameter if does not.
|
||||
func (o OptInt32) Or(d int32) int32 {
|
||||
if v, ok := o.Get(); ok {
|
||||
return v
|
||||
}
|
||||
return d
|
||||
// GetTargetAssetID returns the value of TargetAssetID.
|
||||
func (s *MapfixCreate) GetTargetAssetID() uint64 {
|
||||
return s.TargetAssetID
|
||||
}
|
||||
|
||||
// NewOptInt64 returns new OptInt64 with value set to v.
|
||||
func NewOptInt64(v int64) OptInt64 {
|
||||
return OptInt64{
|
||||
Value: v,
|
||||
Set: true,
|
||||
}
|
||||
// SetOperationID sets the value of OperationID.
|
||||
func (s *MapfixCreate) SetOperationID(val uint32) {
|
||||
s.OperationID = val
|
||||
}
|
||||
|
||||
// OptInt64 is optional int64.
|
||||
type OptInt64 struct {
|
||||
Value int64
|
||||
Set bool
|
||||
// SetAssetOwner sets the value of AssetOwner.
|
||||
func (s *MapfixCreate) SetAssetOwner(val uint64) {
|
||||
s.AssetOwner = val
|
||||
}
|
||||
|
||||
// IsSet returns true if OptInt64 was set.
|
||||
func (o OptInt64) IsSet() bool { return o.Set }
|
||||
|
||||
// Reset unsets value.
|
||||
func (o *OptInt64) Reset() {
|
||||
var v int64
|
||||
o.Value = v
|
||||
o.Set = false
|
||||
// SetDisplayName sets the value of DisplayName.
|
||||
func (s *MapfixCreate) SetDisplayName(val string) {
|
||||
s.DisplayName = val
|
||||
}
|
||||
|
||||
// SetTo sets value to v.
|
||||
func (o *OptInt64) SetTo(v int64) {
|
||||
o.Set = true
|
||||
o.Value = v
|
||||
// SetCreator sets the value of Creator.
|
||||
func (s *MapfixCreate) SetCreator(val string) {
|
||||
s.Creator = val
|
||||
}
|
||||
|
||||
// Get returns value and boolean that denotes whether value was set.
|
||||
func (o OptInt64) Get() (v int64, ok bool) {
|
||||
if !o.Set {
|
||||
return v, false
|
||||
}
|
||||
return o.Value, true
|
||||
// SetGameID sets the value of GameID.
|
||||
func (s *MapfixCreate) SetGameID(val uint32) {
|
||||
s.GameID = val
|
||||
}
|
||||
|
||||
// Or returns value if set, or given parameter if does not.
|
||||
func (o OptInt64) Or(d int64) int64 {
|
||||
if v, ok := o.Get(); ok {
|
||||
return v
|
||||
}
|
||||
return d
|
||||
// SetAssetID sets the value of AssetID.
|
||||
func (s *MapfixCreate) SetAssetID(val uint64) {
|
||||
s.AssetID = val
|
||||
}
|
||||
|
||||
// SetAssetVersion sets the value of AssetVersion.
|
||||
func (s *MapfixCreate) SetAssetVersion(val uint64) {
|
||||
s.AssetVersion = val
|
||||
}
|
||||
|
||||
// SetTargetAssetID sets the value of TargetAssetID.
|
||||
func (s *MapfixCreate) SetTargetAssetID(val uint64) {
|
||||
s.TargetAssetID = val
|
||||
}
|
||||
|
||||
// Ref: #/components/schemas/MapfixID
|
||||
type MapfixID struct {
|
||||
MapfixID uint64 `json:"MapfixID"`
|
||||
}
|
||||
|
||||
// GetMapfixID returns the value of MapfixID.
|
||||
func (s *MapfixID) GetMapfixID() uint64 {
|
||||
return s.MapfixID
|
||||
}
|
||||
|
||||
// SetMapfixID sets the value of MapfixID.
|
||||
func (s *MapfixID) SetMapfixID(val uint64) {
|
||||
s.MapfixID = val
|
||||
}
|
||||
|
||||
// NewOptString returns new OptString with value set to v.
|
||||
@@ -225,18 +243,110 @@ func (o OptString) Or(d string) string {
|
||||
return d
|
||||
}
|
||||
|
||||
// NewOptUint32 returns new OptUint32 with value set to v.
|
||||
func NewOptUint32(v uint32) OptUint32 {
|
||||
return OptUint32{
|
||||
Value: v,
|
||||
Set: true,
|
||||
}
|
||||
}
|
||||
|
||||
// OptUint32 is optional uint32.
|
||||
type OptUint32 struct {
|
||||
Value uint32
|
||||
Set bool
|
||||
}
|
||||
|
||||
// IsSet returns true if OptUint32 was set.
|
||||
func (o OptUint32) IsSet() bool { return o.Set }
|
||||
|
||||
// Reset unsets value.
|
||||
func (o *OptUint32) Reset() {
|
||||
var v uint32
|
||||
o.Value = v
|
||||
o.Set = false
|
||||
}
|
||||
|
||||
// SetTo sets value to v.
|
||||
func (o *OptUint32) SetTo(v uint32) {
|
||||
o.Set = true
|
||||
o.Value = v
|
||||
}
|
||||
|
||||
// Get returns value and boolean that denotes whether value was set.
|
||||
func (o OptUint32) Get() (v uint32, ok bool) {
|
||||
if !o.Set {
|
||||
return v, false
|
||||
}
|
||||
return o.Value, true
|
||||
}
|
||||
|
||||
// Or returns value if set, or given parameter if does not.
|
||||
func (o OptUint32) Or(d uint32) uint32 {
|
||||
if v, ok := o.Get(); ok {
|
||||
return v
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// NewOptUint64 returns new OptUint64 with value set to v.
|
||||
func NewOptUint64(v uint64) OptUint64 {
|
||||
return OptUint64{
|
||||
Value: v,
|
||||
Set: true,
|
||||
}
|
||||
}
|
||||
|
||||
// OptUint64 is optional uint64.
|
||||
type OptUint64 struct {
|
||||
Value uint64
|
||||
Set bool
|
||||
}
|
||||
|
||||
// IsSet returns true if OptUint64 was set.
|
||||
func (o OptUint64) IsSet() bool { return o.Set }
|
||||
|
||||
// Reset unsets value.
|
||||
func (o *OptUint64) Reset() {
|
||||
var v uint64
|
||||
o.Value = v
|
||||
o.Set = false
|
||||
}
|
||||
|
||||
// SetTo sets value to v.
|
||||
func (o *OptUint64) SetTo(v uint64) {
|
||||
o.Set = true
|
||||
o.Value = v
|
||||
}
|
||||
|
||||
// Get returns value and boolean that denotes whether value was set.
|
||||
func (o OptUint64) Get() (v uint64, ok bool) {
|
||||
if !o.Set {
|
||||
return v, false
|
||||
}
|
||||
return o.Value, true
|
||||
}
|
||||
|
||||
// Or returns value if set, or given parameter if does not.
|
||||
func (o OptUint64) Or(d uint64) uint64 {
|
||||
if v, ok := o.Get(); ok {
|
||||
return v
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// Ref: #/components/schemas/Script
|
||||
type Script struct {
|
||||
ID int64 `json:"ID"`
|
||||
ID uint64 `json:"ID"`
|
||||
Name string `json:"Name"`
|
||||
Hash string `json:"Hash"`
|
||||
Source string `json:"Source"`
|
||||
ResourceType int32 `json:"ResourceType"`
|
||||
ResourceID int64 `json:"ResourceID"`
|
||||
ResourceType uint32 `json:"ResourceType"`
|
||||
ResourceID uint64 `json:"ResourceID"`
|
||||
}
|
||||
|
||||
// GetID returns the value of ID.
|
||||
func (s *Script) GetID() int64 {
|
||||
func (s *Script) GetID() uint64 {
|
||||
return s.ID
|
||||
}
|
||||
|
||||
@@ -256,17 +366,17 @@ func (s *Script) GetSource() string {
|
||||
}
|
||||
|
||||
// GetResourceType returns the value of ResourceType.
|
||||
func (s *Script) GetResourceType() int32 {
|
||||
func (s *Script) GetResourceType() uint32 {
|
||||
return s.ResourceType
|
||||
}
|
||||
|
||||
// GetResourceID returns the value of ResourceID.
|
||||
func (s *Script) GetResourceID() int64 {
|
||||
func (s *Script) GetResourceID() uint64 {
|
||||
return s.ResourceID
|
||||
}
|
||||
|
||||
// SetID sets the value of ID.
|
||||
func (s *Script) SetID(val int64) {
|
||||
func (s *Script) SetID(val uint64) {
|
||||
s.ID = val
|
||||
}
|
||||
|
||||
@@ -286,21 +396,21 @@ func (s *Script) SetSource(val string) {
|
||||
}
|
||||
|
||||
// SetResourceType sets the value of ResourceType.
|
||||
func (s *Script) SetResourceType(val int32) {
|
||||
func (s *Script) SetResourceType(val uint32) {
|
||||
s.ResourceType = val
|
||||
}
|
||||
|
||||
// SetResourceID sets the value of ResourceID.
|
||||
func (s *Script) SetResourceID(val int64) {
|
||||
func (s *Script) SetResourceID(val uint64) {
|
||||
s.ResourceID = val
|
||||
}
|
||||
|
||||
// Ref: #/components/schemas/ScriptCreate
|
||||
type ScriptCreate struct {
|
||||
Name string `json:"Name"`
|
||||
Source string `json:"Source"`
|
||||
ResourceType int32 `json:"ResourceType"`
|
||||
ResourceID OptInt64 `json:"ResourceID"`
|
||||
Name string `json:"Name"`
|
||||
Source string `json:"Source"`
|
||||
ResourceType uint32 `json:"ResourceType"`
|
||||
ResourceID OptUint64 `json:"ResourceID"`
|
||||
}
|
||||
|
||||
// GetName returns the value of Name.
|
||||
@@ -314,12 +424,12 @@ func (s *ScriptCreate) GetSource() string {
|
||||
}
|
||||
|
||||
// GetResourceType returns the value of ResourceType.
|
||||
func (s *ScriptCreate) GetResourceType() int32 {
|
||||
func (s *ScriptCreate) GetResourceType() uint32 {
|
||||
return s.ResourceType
|
||||
}
|
||||
|
||||
// GetResourceID returns the value of ResourceID.
|
||||
func (s *ScriptCreate) GetResourceID() OptInt64 {
|
||||
func (s *ScriptCreate) GetResourceID() OptUint64 {
|
||||
return s.ResourceID
|
||||
}
|
||||
|
||||
@@ -334,25 +444,40 @@ func (s *ScriptCreate) SetSource(val string) {
|
||||
}
|
||||
|
||||
// SetResourceType sets the value of ResourceType.
|
||||
func (s *ScriptCreate) SetResourceType(val int32) {
|
||||
func (s *ScriptCreate) SetResourceType(val uint32) {
|
||||
s.ResourceType = val
|
||||
}
|
||||
|
||||
// SetResourceID sets the value of ResourceID.
|
||||
func (s *ScriptCreate) SetResourceID(val OptInt64) {
|
||||
func (s *ScriptCreate) SetResourceID(val OptUint64) {
|
||||
s.ResourceID = val
|
||||
}
|
||||
|
||||
// Ref: #/components/schemas/ScriptID
|
||||
type ScriptID struct {
|
||||
ScriptID uint64 `json:"ScriptID"`
|
||||
}
|
||||
|
||||
// GetScriptID returns the value of ScriptID.
|
||||
func (s *ScriptID) GetScriptID() uint64 {
|
||||
return s.ScriptID
|
||||
}
|
||||
|
||||
// SetScriptID sets the value of ScriptID.
|
||||
func (s *ScriptID) SetScriptID(val uint64) {
|
||||
s.ScriptID = val
|
||||
}
|
||||
|
||||
// Ref: #/components/schemas/ScriptPolicy
|
||||
type ScriptPolicy struct {
|
||||
ID int64 `json:"ID"`
|
||||
ID uint64 `json:"ID"`
|
||||
FromScriptHash string `json:"FromScriptHash"`
|
||||
ToScriptID int64 `json:"ToScriptID"`
|
||||
Policy int32 `json:"Policy"`
|
||||
ToScriptID uint64 `json:"ToScriptID"`
|
||||
Policy uint32 `json:"Policy"`
|
||||
}
|
||||
|
||||
// GetID returns the value of ID.
|
||||
func (s *ScriptPolicy) GetID() int64 {
|
||||
func (s *ScriptPolicy) GetID() uint64 {
|
||||
return s.ID
|
||||
}
|
||||
|
||||
@@ -362,17 +487,17 @@ func (s *ScriptPolicy) GetFromScriptHash() string {
|
||||
}
|
||||
|
||||
// GetToScriptID returns the value of ToScriptID.
|
||||
func (s *ScriptPolicy) GetToScriptID() int64 {
|
||||
func (s *ScriptPolicy) GetToScriptID() uint64 {
|
||||
return s.ToScriptID
|
||||
}
|
||||
|
||||
// GetPolicy returns the value of Policy.
|
||||
func (s *ScriptPolicy) GetPolicy() int32 {
|
||||
func (s *ScriptPolicy) GetPolicy() uint32 {
|
||||
return s.Policy
|
||||
}
|
||||
|
||||
// SetID sets the value of ID.
|
||||
func (s *ScriptPolicy) SetID(val int64) {
|
||||
func (s *ScriptPolicy) SetID(val uint64) {
|
||||
s.ID = val
|
||||
}
|
||||
|
||||
@@ -382,51 +507,165 @@ func (s *ScriptPolicy) SetFromScriptHash(val string) {
|
||||
}
|
||||
|
||||
// SetToScriptID sets the value of ToScriptID.
|
||||
func (s *ScriptPolicy) SetToScriptID(val int64) {
|
||||
func (s *ScriptPolicy) SetToScriptID(val uint64) {
|
||||
s.ToScriptID = val
|
||||
}
|
||||
|
||||
// SetPolicy sets the value of Policy.
|
||||
func (s *ScriptPolicy) SetPolicy(val int32) {
|
||||
func (s *ScriptPolicy) SetPolicy(val uint32) {
|
||||
s.Policy = val
|
||||
}
|
||||
|
||||
// Ref: #/components/schemas/ScriptPolicyCreate
|
||||
type ScriptPolicyCreate struct {
|
||||
FromScriptID int64 `json:"FromScriptID"`
|
||||
ToScriptID int64 `json:"ToScriptID"`
|
||||
Policy int32 `json:"Policy"`
|
||||
FromScriptID uint64 `json:"FromScriptID"`
|
||||
ToScriptID uint64 `json:"ToScriptID"`
|
||||
Policy uint32 `json:"Policy"`
|
||||
}
|
||||
|
||||
// GetFromScriptID returns the value of FromScriptID.
|
||||
func (s *ScriptPolicyCreate) GetFromScriptID() int64 {
|
||||
func (s *ScriptPolicyCreate) GetFromScriptID() uint64 {
|
||||
return s.FromScriptID
|
||||
}
|
||||
|
||||
// GetToScriptID returns the value of ToScriptID.
|
||||
func (s *ScriptPolicyCreate) GetToScriptID() int64 {
|
||||
func (s *ScriptPolicyCreate) GetToScriptID() uint64 {
|
||||
return s.ToScriptID
|
||||
}
|
||||
|
||||
// GetPolicy returns the value of Policy.
|
||||
func (s *ScriptPolicyCreate) GetPolicy() int32 {
|
||||
func (s *ScriptPolicyCreate) GetPolicy() uint32 {
|
||||
return s.Policy
|
||||
}
|
||||
|
||||
// SetFromScriptID sets the value of FromScriptID.
|
||||
func (s *ScriptPolicyCreate) SetFromScriptID(val int64) {
|
||||
func (s *ScriptPolicyCreate) SetFromScriptID(val uint64) {
|
||||
s.FromScriptID = val
|
||||
}
|
||||
|
||||
// SetToScriptID sets the value of ToScriptID.
|
||||
func (s *ScriptPolicyCreate) SetToScriptID(val int64) {
|
||||
func (s *ScriptPolicyCreate) SetToScriptID(val uint64) {
|
||||
s.ToScriptID = val
|
||||
}
|
||||
|
||||
// SetPolicy sets the value of Policy.
|
||||
func (s *ScriptPolicyCreate) SetPolicy(val int32) {
|
||||
func (s *ScriptPolicyCreate) SetPolicy(val uint32) {
|
||||
s.Policy = val
|
||||
}
|
||||
|
||||
// Ref: #/components/schemas/ScriptPolicyID
|
||||
type ScriptPolicyID struct {
|
||||
ScriptPolicyID uint64 `json:"ScriptPolicyID"`
|
||||
}
|
||||
|
||||
// GetScriptPolicyID returns the value of ScriptPolicyID.
|
||||
func (s *ScriptPolicyID) GetScriptPolicyID() uint64 {
|
||||
return s.ScriptPolicyID
|
||||
}
|
||||
|
||||
// SetScriptPolicyID sets the value of ScriptPolicyID.
|
||||
func (s *ScriptPolicyID) SetScriptPolicyID(val uint64) {
|
||||
s.ScriptPolicyID = val
|
||||
}
|
||||
|
||||
// Ref: #/components/schemas/SubmissionCreate
|
||||
type SubmissionCreate struct {
|
||||
OperationID uint32 `json:"OperationID"`
|
||||
AssetOwner uint64 `json:"AssetOwner"`
|
||||
DisplayName string `json:"DisplayName"`
|
||||
Creator string `json:"Creator"`
|
||||
GameID uint32 `json:"GameID"`
|
||||
AssetID uint64 `json:"AssetID"`
|
||||
AssetVersion uint64 `json:"AssetVersion"`
|
||||
}
|
||||
|
||||
// GetOperationID returns the value of OperationID.
|
||||
func (s *SubmissionCreate) GetOperationID() uint32 {
|
||||
return s.OperationID
|
||||
}
|
||||
|
||||
// GetAssetOwner returns the value of AssetOwner.
|
||||
func (s *SubmissionCreate) GetAssetOwner() uint64 {
|
||||
return s.AssetOwner
|
||||
}
|
||||
|
||||
// GetDisplayName returns the value of DisplayName.
|
||||
func (s *SubmissionCreate) GetDisplayName() string {
|
||||
return s.DisplayName
|
||||
}
|
||||
|
||||
// GetCreator returns the value of Creator.
|
||||
func (s *SubmissionCreate) GetCreator() string {
|
||||
return s.Creator
|
||||
}
|
||||
|
||||
// GetGameID returns the value of GameID.
|
||||
func (s *SubmissionCreate) GetGameID() uint32 {
|
||||
return s.GameID
|
||||
}
|
||||
|
||||
// GetAssetID returns the value of AssetID.
|
||||
func (s *SubmissionCreate) GetAssetID() uint64 {
|
||||
return s.AssetID
|
||||
}
|
||||
|
||||
// GetAssetVersion returns the value of AssetVersion.
|
||||
func (s *SubmissionCreate) GetAssetVersion() uint64 {
|
||||
return s.AssetVersion
|
||||
}
|
||||
|
||||
// SetOperationID sets the value of OperationID.
|
||||
func (s *SubmissionCreate) SetOperationID(val uint32) {
|
||||
s.OperationID = val
|
||||
}
|
||||
|
||||
// SetAssetOwner sets the value of AssetOwner.
|
||||
func (s *SubmissionCreate) SetAssetOwner(val uint64) {
|
||||
s.AssetOwner = val
|
||||
}
|
||||
|
||||
// SetDisplayName sets the value of DisplayName.
|
||||
func (s *SubmissionCreate) SetDisplayName(val string) {
|
||||
s.DisplayName = val
|
||||
}
|
||||
|
||||
// SetCreator sets the value of Creator.
|
||||
func (s *SubmissionCreate) SetCreator(val string) {
|
||||
s.Creator = val
|
||||
}
|
||||
|
||||
// SetGameID sets the value of GameID.
|
||||
func (s *SubmissionCreate) SetGameID(val uint32) {
|
||||
s.GameID = val
|
||||
}
|
||||
|
||||
// SetAssetID sets the value of AssetID.
|
||||
func (s *SubmissionCreate) SetAssetID(val uint64) {
|
||||
s.AssetID = val
|
||||
}
|
||||
|
||||
// SetAssetVersion sets the value of AssetVersion.
|
||||
func (s *SubmissionCreate) SetAssetVersion(val uint64) {
|
||||
s.AssetVersion = val
|
||||
}
|
||||
|
||||
// Ref: #/components/schemas/SubmissionID
|
||||
type SubmissionID struct {
|
||||
SubmissionID uint64 `json:"SubmissionID"`
|
||||
}
|
||||
|
||||
// GetSubmissionID returns the value of SubmissionID.
|
||||
func (s *SubmissionID) GetSubmissionID() uint64 {
|
||||
return s.SubmissionID
|
||||
}
|
||||
|
||||
// SetSubmissionID sets the value of SubmissionID.
|
||||
func (s *SubmissionID) SetSubmissionID(val uint64) {
|
||||
s.SubmissionID = val
|
||||
}
|
||||
|
||||
// UpdateMapfixValidatedModelNoContent is response for UpdateMapfixValidatedModel operation.
|
||||
type UpdateMapfixValidatedModelNoContent struct{}
|
||||
|
||||
// UpdateSubmissionValidatedModelNoContent is response for UpdateSubmissionValidatedModel operation.
|
||||
type UpdateSubmissionValidatedModelNoContent struct{}
|
||||
|
||||
@@ -8,12 +8,48 @@ import (
|
||||
|
||||
// Handler handles operations described by OpenAPI v3 specification.
|
||||
type Handler interface {
|
||||
// ActionMapfixAccepted implements actionMapfixAccepted operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-failed
|
||||
ActionMapfixAccepted(ctx context.Context, params ActionMapfixAcceptedParams) error
|
||||
// ActionMapfixSubmitted implements actionMapfixSubmitted operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Submitting -> Submitted.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-submitted
|
||||
ActionMapfixSubmitted(ctx context.Context, params ActionMapfixSubmittedParams) error
|
||||
// ActionMapfixUploaded implements actionMapfixUploaded operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Uploading -> Uploaded.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-uploaded
|
||||
ActionMapfixUploaded(ctx context.Context, params ActionMapfixUploadedParams) error
|
||||
// ActionMapfixValidated implements actionMapfixValidated operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Validating -> Validated.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-validated
|
||||
ActionMapfixValidated(ctx context.Context, params ActionMapfixValidatedParams) error
|
||||
// ActionOperationFailed implements actionOperationFailed operation.
|
||||
//
|
||||
// (Internal endpoint) Fail an operation and write a StatusMessage.
|
||||
//
|
||||
// POST /operations/{OperationID}/status/operation-failed
|
||||
ActionOperationFailed(ctx context.Context, params ActionOperationFailedParams) error
|
||||
// ActionSubmissionAccepted implements actionSubmissionAccepted operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/validator-failed
|
||||
ActionSubmissionAccepted(ctx context.Context, params ActionSubmissionAcceptedParams) error
|
||||
// ActionSubmissionSubmitted implements actionSubmissionSubmitted operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Submitting -> Submitted.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/validator-submitted
|
||||
ActionSubmissionSubmitted(ctx context.Context, params ActionSubmissionSubmittedParams) error
|
||||
// ActionSubmissionUploaded implements actionSubmissionUploaded operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Uploading -> Uploaded.
|
||||
@@ -26,18 +62,30 @@ type Handler interface {
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/validator-validated
|
||||
ActionSubmissionValidated(ctx context.Context, params ActionSubmissionValidatedParams) error
|
||||
// CreateMapfix implements createMapfix operation.
|
||||
//
|
||||
// Create a mapfix.
|
||||
//
|
||||
// POST /mapfixes
|
||||
CreateMapfix(ctx context.Context, req *MapfixCreate) (*MapfixID, error)
|
||||
// CreateScript implements createScript operation.
|
||||
//
|
||||
// Create a new script.
|
||||
//
|
||||
// POST /scripts
|
||||
CreateScript(ctx context.Context, req *ScriptCreate) (*ID, error)
|
||||
CreateScript(ctx context.Context, req *ScriptCreate) (*ScriptID, error)
|
||||
// CreateScriptPolicy implements createScriptPolicy operation.
|
||||
//
|
||||
// Create a new script policy.
|
||||
//
|
||||
// POST /script-policy
|
||||
CreateScriptPolicy(ctx context.Context, req *ScriptPolicyCreate) (*ID, error)
|
||||
CreateScriptPolicy(ctx context.Context, req *ScriptPolicyCreate) (*ScriptPolicyID, error)
|
||||
// CreateSubmission implements createSubmission operation.
|
||||
//
|
||||
// Create a new submission.
|
||||
//
|
||||
// POST /submissions
|
||||
CreateSubmission(ctx context.Context, req *SubmissionCreate) (*SubmissionID, error)
|
||||
// GetScript implements getScript operation.
|
||||
//
|
||||
// Get the specified script by ID.
|
||||
@@ -56,6 +104,12 @@ type Handler interface {
|
||||
//
|
||||
// GET /scripts
|
||||
ListScripts(ctx context.Context, params ListScriptsParams) ([]Script, error)
|
||||
// UpdateMapfixValidatedModel implements updateMapfixValidatedModel operation.
|
||||
//
|
||||
// Update validated model.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/validated-model
|
||||
UpdateMapfixValidatedModel(ctx context.Context, params UpdateMapfixValidatedModelParams) error
|
||||
// UpdateSubmissionValidatedModel implements updateSubmissionValidatedModel operation.
|
||||
//
|
||||
// Update validated model.
|
||||
|
||||
@@ -13,6 +13,51 @@ type UnimplementedHandler struct{}
|
||||
|
||||
var _ Handler = UnimplementedHandler{}
|
||||
|
||||
// ActionMapfixAccepted implements actionMapfixAccepted operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-failed
|
||||
func (UnimplementedHandler) ActionMapfixAccepted(ctx context.Context, params ActionMapfixAcceptedParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixSubmitted implements actionMapfixSubmitted operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Submitting -> Submitted.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-submitted
|
||||
func (UnimplementedHandler) ActionMapfixSubmitted(ctx context.Context, params ActionMapfixSubmittedParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixUploaded implements actionMapfixUploaded operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Uploading -> Uploaded.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-uploaded
|
||||
func (UnimplementedHandler) ActionMapfixUploaded(ctx context.Context, params ActionMapfixUploadedParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionMapfixValidated implements actionMapfixValidated operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Validating -> Validated.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-validated
|
||||
func (UnimplementedHandler) ActionMapfixValidated(ctx context.Context, params ActionMapfixValidatedParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionOperationFailed implements actionOperationFailed operation.
|
||||
//
|
||||
// (Internal endpoint) Fail an operation and write a StatusMessage.
|
||||
//
|
||||
// POST /operations/{OperationID}/status/operation-failed
|
||||
func (UnimplementedHandler) ActionOperationFailed(ctx context.Context, params ActionOperationFailedParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionSubmissionAccepted implements actionSubmissionAccepted operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
|
||||
@@ -22,6 +67,15 @@ func (UnimplementedHandler) ActionSubmissionAccepted(ctx context.Context, params
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionSubmissionSubmitted implements actionSubmissionSubmitted operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Submitting -> Submitted.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/validator-submitted
|
||||
func (UnimplementedHandler) ActionSubmissionSubmitted(ctx context.Context, params ActionSubmissionSubmittedParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// ActionSubmissionUploaded implements actionSubmissionUploaded operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Uploading -> Uploaded.
|
||||
@@ -40,12 +94,21 @@ func (UnimplementedHandler) ActionSubmissionValidated(ctx context.Context, param
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// CreateMapfix implements createMapfix operation.
|
||||
//
|
||||
// Create a mapfix.
|
||||
//
|
||||
// POST /mapfixes
|
||||
func (UnimplementedHandler) CreateMapfix(ctx context.Context, req *MapfixCreate) (r *MapfixID, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// CreateScript implements createScript operation.
|
||||
//
|
||||
// Create a new script.
|
||||
//
|
||||
// POST /scripts
|
||||
func (UnimplementedHandler) CreateScript(ctx context.Context, req *ScriptCreate) (r *ID, _ error) {
|
||||
func (UnimplementedHandler) CreateScript(ctx context.Context, req *ScriptCreate) (r *ScriptID, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
@@ -54,7 +117,16 @@ func (UnimplementedHandler) CreateScript(ctx context.Context, req *ScriptCreate)
|
||||
// Create a new script policy.
|
||||
//
|
||||
// POST /script-policy
|
||||
func (UnimplementedHandler) CreateScriptPolicy(ctx context.Context, req *ScriptPolicyCreate) (r *ID, _ error) {
|
||||
func (UnimplementedHandler) CreateScriptPolicy(ctx context.Context, req *ScriptPolicyCreate) (r *ScriptPolicyID, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// CreateSubmission implements createSubmission operation.
|
||||
//
|
||||
// Create a new submission.
|
||||
//
|
||||
// POST /submissions
|
||||
func (UnimplementedHandler) CreateSubmission(ctx context.Context, req *SubmissionCreate) (r *SubmissionID, _ error) {
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
@@ -85,6 +157,15 @@ func (UnimplementedHandler) ListScripts(ctx context.Context, params ListScriptsP
|
||||
return r, ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// UpdateMapfixValidatedModel implements updateMapfixValidatedModel operation.
|
||||
//
|
||||
// Update validated model.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/validated-model
|
||||
func (UnimplementedHandler) UpdateMapfixValidatedModel(ctx context.Context, params UpdateMapfixValidatedModelParams) error {
|
||||
return ht.ErrNotImplemented
|
||||
}
|
||||
|
||||
// UpdateSubmissionValidatedModel implements updateSubmissionValidatedModel operation.
|
||||
//
|
||||
// Update validated model.
|
||||
|
||||
@@ -8,12 +8,289 @@ import (
|
||||
"github.com/ogen-go/ogen/validate"
|
||||
)
|
||||
|
||||
func (s *Error) Validate() error {
|
||||
if s == nil {
|
||||
return validate.ErrNilPointer
|
||||
}
|
||||
|
||||
var failures []validate.FieldError
|
||||
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(s.Code)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "code",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ErrorStatusCode) Validate() error {
|
||||
if s == nil {
|
||||
return validate.ErrNilPointer
|
||||
}
|
||||
|
||||
var failures []validate.FieldError
|
||||
if err := func() error {
|
||||
if err := s.Response.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "Response",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MapfixCreate) Validate() error {
|
||||
if s == nil {
|
||||
return validate.ErrNilPointer
|
||||
}
|
||||
|
||||
var failures []validate.FieldError
|
||||
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(s.OperationID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "OperationID",
|
||||
Error: 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(s.AssetOwner)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "AssetOwner",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if err := func() error {
|
||||
if err := (validate.String{
|
||||
MinLength: 0,
|
||||
MinLengthSet: false,
|
||||
MaxLength: 128,
|
||||
MaxLengthSet: true,
|
||||
Email: false,
|
||||
Hostname: false,
|
||||
Regex: nil,
|
||||
}).Validate(string(s.DisplayName)); err != nil {
|
||||
return errors.Wrap(err, "string")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "DisplayName",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if err := func() error {
|
||||
if err := (validate.String{
|
||||
MinLength: 0,
|
||||
MinLengthSet: false,
|
||||
MaxLength: 128,
|
||||
MaxLengthSet: true,
|
||||
Email: false,
|
||||
Hostname: false,
|
||||
Regex: nil,
|
||||
}).Validate(string(s.Creator)); err != nil {
|
||||
return errors.Wrap(err, "string")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "Creator",
|
||||
Error: 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(s.GameID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "GameID",
|
||||
Error: 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(s.AssetID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "AssetID",
|
||||
Error: 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(s.AssetVersion)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "AssetVersion",
|
||||
Error: 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(s.TargetAssetID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "TargetAssetID",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MapfixID) Validate() error {
|
||||
if s == nil {
|
||||
return validate.ErrNilPointer
|
||||
}
|
||||
|
||||
var failures []validate.FieldError
|
||||
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(s.MapfixID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "MapfixID",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Script) Validate() error {
|
||||
if s == nil {
|
||||
return validate.ErrNilPointer
|
||||
}
|
||||
|
||||
var failures []validate.FieldError
|
||||
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(s.ID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "ID",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if err := func() error {
|
||||
if err := (validate.String{
|
||||
MinLength: 0,
|
||||
@@ -71,6 +348,46 @@ func (s *Script) Validate() error {
|
||||
Error: 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(s.ResourceType)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "ResourceType",
|
||||
Error: 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(s.ResourceID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "ResourceID",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
@@ -121,6 +438,85 @@ func (s *ScriptCreate) Validate() error {
|
||||
Error: 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(s.ResourceType)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "ResourceType",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if err := func() error {
|
||||
if value, ok := s.ResourceID.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: "ResourceID",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ScriptID) Validate() error {
|
||||
if s == nil {
|
||||
return validate.ErrNilPointer
|
||||
}
|
||||
|
||||
var failures []validate.FieldError
|
||||
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(s.ScriptID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "ScriptID",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
@@ -133,6 +529,26 @@ func (s *ScriptPolicy) Validate() error {
|
||||
}
|
||||
|
||||
var failures []validate.FieldError
|
||||
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(s.ID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "ID",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if err := func() error {
|
||||
if err := (validate.String{
|
||||
MinLength: 16,
|
||||
@@ -152,6 +568,332 @@ func (s *ScriptPolicy) Validate() error {
|
||||
Error: 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(s.ToScriptID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "ToScriptID",
|
||||
Error: 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(s.Policy)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "Policy",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ScriptPolicyCreate) Validate() error {
|
||||
if s == nil {
|
||||
return validate.ErrNilPointer
|
||||
}
|
||||
|
||||
var failures []validate.FieldError
|
||||
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(s.FromScriptID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "FromScriptID",
|
||||
Error: 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(s.ToScriptID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "ToScriptID",
|
||||
Error: 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(s.Policy)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "Policy",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ScriptPolicyID) Validate() error {
|
||||
if s == nil {
|
||||
return validate.ErrNilPointer
|
||||
}
|
||||
|
||||
var failures []validate.FieldError
|
||||
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(s.ScriptPolicyID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "ScriptPolicyID",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SubmissionCreate) Validate() error {
|
||||
if s == nil {
|
||||
return validate.ErrNilPointer
|
||||
}
|
||||
|
||||
var failures []validate.FieldError
|
||||
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(s.OperationID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "OperationID",
|
||||
Error: 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(s.AssetOwner)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "AssetOwner",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if err := func() error {
|
||||
if err := (validate.String{
|
||||
MinLength: 0,
|
||||
MinLengthSet: false,
|
||||
MaxLength: 128,
|
||||
MaxLengthSet: true,
|
||||
Email: false,
|
||||
Hostname: false,
|
||||
Regex: nil,
|
||||
}).Validate(string(s.DisplayName)); err != nil {
|
||||
return errors.Wrap(err, "string")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "DisplayName",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if err := func() error {
|
||||
if err := (validate.String{
|
||||
MinLength: 0,
|
||||
MinLengthSet: false,
|
||||
MaxLength: 128,
|
||||
MaxLengthSet: true,
|
||||
Email: false,
|
||||
Hostname: false,
|
||||
Regex: nil,
|
||||
}).Validate(string(s.Creator)); err != nil {
|
||||
return errors.Wrap(err, "string")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "Creator",
|
||||
Error: 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(s.GameID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "GameID",
|
||||
Error: 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(s.AssetID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "AssetID",
|
||||
Error: 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(s.AssetVersion)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "AssetVersion",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SubmissionID) Validate() error {
|
||||
if s == nil {
|
||||
return validate.ErrNilPointer
|
||||
}
|
||||
|
||||
var failures []validate.FieldError
|
||||
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(s.SubmissionID)); err != nil {
|
||||
return errors.Wrap(err, "int")
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
failures = append(failures, validate.FieldError{
|
||||
Name: "SubmissionID",
|
||||
Error: err,
|
||||
})
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return &validate.Error{Fields: failures}
|
||||
}
|
||||
|
||||
53
pkg/model/audit_event.go
Normal file
53
pkg/model/audit_event.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
type AuditEventType uint32
|
||||
|
||||
// User clicked "Submit", "Accept" etc
|
||||
const AuditEventTypeAction AuditEventType = 0
|
||||
type AuditEventDataAction struct {
|
||||
TargetStatus uint32 `json:"target_status"`
|
||||
}
|
||||
|
||||
// User wrote a comment
|
||||
const AuditEventTypeComment AuditEventType = 1
|
||||
type AuditEventDataComment struct {
|
||||
Comment string `json:"comment"`
|
||||
}
|
||||
|
||||
// User changed Model
|
||||
const AuditEventTypeChangeModel AuditEventType = 2
|
||||
type AuditEventDataChangeModel struct {
|
||||
OldModelID uint64 `json:"old_model_id"`
|
||||
OldModelVersion uint64 `json:"old_model_version"`
|
||||
NewModelID uint64 `json:"new_model_id"`
|
||||
NewModelVersion uint64 `json:"new_model_version"`
|
||||
}
|
||||
// Validator validates model
|
||||
const AuditEventTypeChangeValidatedModel AuditEventType = 3
|
||||
type AuditEventDataChangeValidatedModel struct {
|
||||
ValidatedModelID uint64 `json:"validated_model_id"`
|
||||
ValidatedModelVersion uint64 `json:"validated_model_version"`
|
||||
}
|
||||
|
||||
// User changed DisplayName / Creator
|
||||
const AuditEventTypeChangeDisplayName AuditEventType = 4
|
||||
const AuditEventTypeChangeCreator AuditEventType = 5
|
||||
type AuditEventDataChangeName struct {
|
||||
OldName string `json:"old_name"`
|
||||
NewName string `json:"new_name"`
|
||||
}
|
||||
|
||||
type AuditEvent struct {
|
||||
ID uint64 `gorm:"primaryKey"`
|
||||
CreatedAt time.Time
|
||||
User uint64
|
||||
ResourceType ResourceType // is this a submission or is it a mapfix
|
||||
ResourceID uint64 // submission / mapfix / map ID
|
||||
EventType AuditEventType
|
||||
EventData json.RawMessage `gorm:"type:jsonb"`
|
||||
}
|
||||
43
pkg/model/mapfix.go
Normal file
43
pkg/model/mapfix.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type MapfixStatus uint32
|
||||
|
||||
const (
|
||||
// Phase: Creation
|
||||
MapfixStatusUnderConstruction MapfixStatus = 0
|
||||
MapfixStatusChangesRequested MapfixStatus = 1
|
||||
|
||||
// Phase: Review
|
||||
MapfixStatusSubmitting MapfixStatus = 2
|
||||
MapfixStatusSubmitted MapfixStatus = 3
|
||||
|
||||
// Phase: Testing
|
||||
MapfixStatusAcceptedUnvalidated MapfixStatus = 4 // pending script review, can re-trigger validation
|
||||
MapfixStatusValidating MapfixStatus = 5
|
||||
MapfixStatusValidated MapfixStatus = 6
|
||||
MapfixStatusUploading MapfixStatus = 7
|
||||
|
||||
// Phase: Final MapfixStatus
|
||||
MapfixStatusUploaded MapfixStatus = 8 // uploaded to the group, but pending release
|
||||
MapfixStatusRejected MapfixStatus = 9
|
||||
)
|
||||
|
||||
type Mapfix struct {
|
||||
ID uint64 `gorm:"primaryKey"`
|
||||
DisplayName string
|
||||
Creator string
|
||||
GameID uint32
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
Submitter uint64 // UserID
|
||||
AssetID uint64
|
||||
AssetVersion uint64
|
||||
ValidatedAssetID uint64
|
||||
ValidatedAssetVersion uint64
|
||||
Completed bool // Has this version of the map been completed at least once on maptest
|
||||
TargetAssetID uint64 // where to upload map fix. if the TargetAssetID is 0, it's a new map.
|
||||
StatusID MapfixStatus
|
||||
StatusMessage string
|
||||
}
|
||||
@@ -5,25 +5,44 @@ package model
|
||||
|
||||
// Requests are sent from maps-service to validator
|
||||
|
||||
type ValidateRequest struct {
|
||||
type CreateSubmissionRequest struct {
|
||||
// operation_id is passed back in the response message
|
||||
OperationID uint32
|
||||
ModelID uint64
|
||||
}
|
||||
|
||||
type CreateMapfixRequest struct {
|
||||
OperationID uint32
|
||||
ModelID uint64
|
||||
TargetAssetID uint64
|
||||
}
|
||||
|
||||
type ValidateSubmissionRequest struct {
|
||||
// submission_id is passed back in the response message
|
||||
SubmissionID int64
|
||||
ModelID int64
|
||||
ModelVersion int64
|
||||
ValidatedModelID *int64 // optional value
|
||||
SubmissionID uint64
|
||||
ModelID uint64
|
||||
ModelVersion uint64
|
||||
ValidatedModelID *uint64 // optional value
|
||||
}
|
||||
|
||||
type ValidateMapfixRequest struct {
|
||||
MapfixID uint64
|
||||
ModelID uint64
|
||||
ModelVersion uint64
|
||||
ValidatedModelID *uint64 // optional value
|
||||
}
|
||||
|
||||
// Create a new map
|
||||
type UploadNewRequest struct {
|
||||
SubmissionID int64
|
||||
ModelID int64
|
||||
ModelVersion int64
|
||||
type UploadSubmissionRequest struct {
|
||||
SubmissionID uint64
|
||||
ModelID uint64
|
||||
ModelVersion uint64
|
||||
ModelName string
|
||||
}
|
||||
|
||||
type UploadFixRequest struct {
|
||||
SubmissionID int64
|
||||
ModelID int64
|
||||
ModelVersion int64
|
||||
TargetAssetID int64
|
||||
type UploadMapfixRequest struct {
|
||||
MapfixID uint64
|
||||
ModelID uint64
|
||||
ModelVersion uint64
|
||||
TargetAssetID uint64
|
||||
}
|
||||
|
||||
19
pkg/model/operation.go
Normal file
19
pkg/model/operation.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type OperationStatus uint32
|
||||
const (
|
||||
OperationStatusCreated OperationStatus = 0
|
||||
OperationStatusCompleted OperationStatus = 1
|
||||
OperationStatusFailed OperationStatus = 2
|
||||
)
|
||||
|
||||
type Operation struct {
|
||||
ID uint32 `gorm:"primaryKey"`
|
||||
CreatedAt time.Time
|
||||
Owner uint64 // UserID
|
||||
StatusID OperationStatus
|
||||
StatusMessage string
|
||||
Path string // redirect to view completed operation e.g. "/mapfixes/4"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package model
|
||||
|
||||
type Page struct {
|
||||
Number int32
|
||||
Size int32
|
||||
Number uint32
|
||||
Size uint32
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package model
|
||||
|
||||
import "time"
|
||||
|
||||
type Policy int32
|
||||
type Policy uint32
|
||||
|
||||
const (
|
||||
ScriptPolicyNone Policy = 0 // not yet reviewed
|
||||
@@ -13,7 +13,7 @@ const (
|
||||
)
|
||||
|
||||
type ScriptPolicy struct {
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
ID uint64 `gorm:"primaryKey"`
|
||||
// Hash of the source code that leads to this policy.
|
||||
// If this is a replacement mapping, the original source may not be pointed to by any policy.
|
||||
// The original source should still exist in the scripts table, which can be located by the same hash.
|
||||
@@ -21,7 +21,7 @@ type ScriptPolicy struct {
|
||||
// The ID of the replacement source (ScriptPolicyReplace)
|
||||
// or verbatim source (ScriptPolicyAllowed)
|
||||
// or 0 (other)
|
||||
ToScriptID int64
|
||||
ToScriptID uint64
|
||||
Policy Policy
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
|
||||
@@ -23,7 +23,7 @@ func HashParse(hash string) (uint64, error){
|
||||
return strconv.ParseUint(hash, 16, 64)
|
||||
}
|
||||
|
||||
type ResourceType int32
|
||||
type ResourceType uint32
|
||||
const (
|
||||
ResourceUnknown ResourceType = 0
|
||||
ResourceMapfix ResourceType = 1
|
||||
@@ -31,12 +31,17 @@ const (
|
||||
)
|
||||
|
||||
type Script struct {
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
ID uint64 `gorm:"primaryKey"`
|
||||
Name string
|
||||
Hash int64 // postgres does not support unsigned integers, so we have to pretend
|
||||
hash uint64
|
||||
Source string
|
||||
ResourceType ResourceType // is this a submission or is it a mapfix
|
||||
ResourceID int64 // which submission / mapfix did this script first appear in
|
||||
ResourceID uint64 // which submission / mapfix did this script first appear in
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
// postgres does not support unsigned integers, so we have to pretend
|
||||
func (script *Script) GetPostgresInt64() (int64) {
|
||||
return int64(script.hash)
|
||||
}
|
||||
|
||||
@@ -2,40 +2,43 @@ package model
|
||||
|
||||
import "time"
|
||||
|
||||
type SubmissionStatus int32
|
||||
type SubmissionStatus uint32
|
||||
|
||||
const (
|
||||
// Phase: Final SubmissionStatus
|
||||
SubmissionStatusReleased SubmissionStatus = 9
|
||||
SubmissionStatusRejected SubmissionStatus = 8
|
||||
// Phase: Creation
|
||||
SubmissionStatusUnderConstruction SubmissionStatus = 0
|
||||
SubmissionStatusChangesRequested SubmissionStatus = 1
|
||||
|
||||
// Phase: Review
|
||||
SubmissionStatusSubmitting SubmissionStatus = 2
|
||||
SubmissionStatusSubmitted SubmissionStatus = 3
|
||||
|
||||
// Phase: Testing
|
||||
SubmissionStatusUploaded SubmissionStatus = 7 // uploaded to the group, but pending release
|
||||
SubmissionStatusUploading SubmissionStatus = 6
|
||||
SubmissionStatusValidated SubmissionStatus = 5
|
||||
SubmissionStatusValidating SubmissionStatus = 4
|
||||
SubmissionStatusAccepted SubmissionStatus = 3 // pending script review, can re-trigger validation
|
||||
SubmissionStatusAcceptedUnvalidated SubmissionStatus = 4 // pending script review, can re-trigger validation
|
||||
SubmissionStatusValidating SubmissionStatus = 5
|
||||
SubmissionStatusValidated SubmissionStatus = 6
|
||||
SubmissionStatusUploading SubmissionStatus = 7
|
||||
SubmissionStatusUploaded SubmissionStatus = 8 // uploaded to the group, but pending release
|
||||
|
||||
// Phase: Creation
|
||||
SubmissionStatusChangesRequested SubmissionStatus = 2
|
||||
SubmissionStatusSubmitted SubmissionStatus = 1
|
||||
SubmissionStatusUnderConstruction SubmissionStatus = 0
|
||||
// Phase: Final SubmissionStatus
|
||||
SubmissionStatusRejected SubmissionStatus = 9
|
||||
SubmissionStatusReleased SubmissionStatus = 10
|
||||
)
|
||||
|
||||
type Submission struct {
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
ID uint64 `gorm:"primaryKey"`
|
||||
DisplayName string
|
||||
Creator string
|
||||
GameID int32
|
||||
GameID uint32
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
Submitter int64 // UserID
|
||||
AssetID int64
|
||||
AssetVersion int64
|
||||
ValidatedAssetID int64
|
||||
ValidatedAssetVersion int64
|
||||
Submitter uint64 // UserID
|
||||
AssetID uint64
|
||||
AssetVersion uint64
|
||||
ValidatedAssetID uint64
|
||||
ValidatedAssetVersion uint64
|
||||
Completed bool // Has this version of the map been completed at least once on maptest
|
||||
UploadedAssetID int64 // where to upload map fix. if the TargetAssetID is 0, it's a new map.
|
||||
UploadedAssetID uint64 // where to upload map fix. if the TargetAssetID is 0, it's a new map.
|
||||
StatusID SubmissionStatus
|
||||
StatusMessage string
|
||||
}
|
||||
|
||||
200
pkg/service/audit_events.go
Normal file
200
pkg/service/audit_events.go
Normal file
@@ -0,0 +1,200 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
// CreateMapfixAuditComment implements createMapfixAuditComment operation.
|
||||
//
|
||||
// Post a comment to the audit log
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/comment
|
||||
func (svc *Service) CreateMapfixAuditComment(ctx context.Context, req api.CreateMapfixAuditCommentReq, params api.CreateMapfixAuditCommentParams) (error) {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleMapfixReview()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapfixReview
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data := []byte{}
|
||||
_, err = req.Read(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
Comment := string(data)
|
||||
|
||||
event_data := model.AuditEventDataComment{
|
||||
Comment: Comment,
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeComment,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListMapfixAuditEvents invokes listMapfixAuditEvents operation.
|
||||
//
|
||||
// Retrieve a list of audit events.
|
||||
//
|
||||
// GET /mapfixes/{MapfixID}/audit-events
|
||||
func (svc *Service) ListMapfixAuditEvents(ctx context.Context, params api.ListMapfixAuditEventsParams) ([]api.AuditEvent, error) {
|
||||
filter := datastore.Optional()
|
||||
|
||||
filter.AddPostgresInt32("resource_type", uint32(model.ResourceMapfix))
|
||||
filter.AddPostgresInt64("resource_id", params.MapfixID)
|
||||
|
||||
items, err := svc.DB.AuditEvents().List(ctx, filter, model.Page{
|
||||
Number: params.Page,
|
||||
Size: params.Limit,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []api.AuditEvent
|
||||
for _, item := range items {
|
||||
EventData := api.AuditEventEventData{}
|
||||
err = EventData.UnmarshalJSON(item.EventData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp = append(resp, api.AuditEvent{
|
||||
ID: item.ID,
|
||||
Date: item.CreatedAt.Unix(),
|
||||
User: item.User,
|
||||
ResourceType: uint32(item.ResourceType),
|
||||
ResourceID: item.ResourceID,
|
||||
EventType: uint32(item.EventType),
|
||||
EventData: EventData,
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// CreateSubmissionAuditComment implements createSubmissionAuditComment operation.
|
||||
//
|
||||
// Post a comment to the audit log
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/comment
|
||||
func (svc *Service) CreateSubmissionAuditComment(ctx context.Context, req api.CreateSubmissionAuditCommentReq, params api.CreateSubmissionAuditCommentParams) (error) {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleSubmissionReview()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleSubmissionReview
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data := []byte{}
|
||||
_, err = req.Read(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
Comment := string(data)
|
||||
|
||||
event_data := model.AuditEventDataComment{
|
||||
Comment: Comment,
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeComment,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListSubmissionAuditEvents invokes listSubmissionAuditEvents operation.
|
||||
//
|
||||
// Retrieve a list of audit events.
|
||||
//
|
||||
// GET /submissions/{SubmissionID}/audit-events
|
||||
func (svc *Service) ListSubmissionAuditEvents(ctx context.Context, params api.ListSubmissionAuditEventsParams) ([]api.AuditEvent, error) {
|
||||
filter := datastore.Optional()
|
||||
|
||||
filter.AddPostgresInt32("resource_type", uint32(model.ResourceSubmission))
|
||||
filter.AddPostgresInt64("resource_id", params.SubmissionID)
|
||||
|
||||
items, err := svc.DB.AuditEvents().List(ctx, filter, model.Page{
|
||||
Number: params.Page,
|
||||
Size: params.Limit,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []api.AuditEvent
|
||||
for _, item := range items {
|
||||
EventData := api.AuditEventEventData{}
|
||||
err = EventData.UnmarshalJSON(item.EventData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp = append(resp, api.AuditEvent{
|
||||
ID: item.ID,
|
||||
Date: item.CreatedAt.Unix(),
|
||||
User: item.User,
|
||||
ResourceType: uint32(item.ResourceType),
|
||||
ResourceID: item.ResourceID,
|
||||
EventType: uint32(item.EventType),
|
||||
EventData: EventData,
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
991
pkg/service/mapfixes.go
Normal file
991
pkg/service/mapfixes.go
Normal file
@@ -0,0 +1,991 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.itzana.me/strafesnet/go-grpc/maps"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
var(
|
||||
CreationPhaseMapfixesLimit = 20
|
||||
CreationPhaseMapfixStatuses = []model.MapfixStatus{
|
||||
model.MapfixStatusChangesRequested,
|
||||
model.MapfixStatusSubmitted,
|
||||
model.MapfixStatusUnderConstruction,
|
||||
}
|
||||
// limit mapfixes in the pipeline to one per target map
|
||||
ActiveAcceptedMapfixStatuses = []model.MapfixStatus{
|
||||
model.MapfixStatusUploading,
|
||||
model.MapfixStatusValidated,
|
||||
model.MapfixStatusValidating,
|
||||
model.MapfixStatusAcceptedUnvalidated,
|
||||
}
|
||||
// Allow 5 mapfixes every 10 minutes
|
||||
CreateMapfixRateLimit int64 = 5
|
||||
CreateMapfixRecencyWindow = time.Second*600
|
||||
)
|
||||
|
||||
var (
|
||||
ErrCreationPhaseMapfixesLimit = errors.New("Active mapfixes limited to 20")
|
||||
ErrActiveMapfixSameTargetAssetID = errors.New("There is an active mapfix with the same TargetAssetID")
|
||||
ErrAcceptOwnMapfix = fmt.Errorf("%w: You cannot accept your own mapfix as the submitter", ErrPermissionDenied)
|
||||
ErrCreateMapfixRateLimit = errors.New("You must not create more than 5 mapfixes every 10 minutes")
|
||||
)
|
||||
|
||||
// POST /mapfixes
|
||||
func (svc *Service) CreateMapfix(ctx context.Context, request *api.MapfixTriggerCreate) (*api.OperationID, error) {
|
||||
// sanitization
|
||||
if request.AssetID<0 || request.TargetAssetID<0{
|
||||
return nil, ErrNegativeID
|
||||
}
|
||||
var ModelID=uint64(request.AssetID);
|
||||
var TargetAssetID=uint64(request.TargetAssetID);
|
||||
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return nil, ErrUserInfo
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check if user's mapfixes in the creation phase exceeds the limit
|
||||
{
|
||||
filter := datastore.Optional()
|
||||
filter.Add("submitter", int64(userId))
|
||||
filter.Add("status_id", CreationPhaseMapfixStatuses)
|
||||
creation_mapfixes, err := svc.DB.Mapfixes().List(ctx, filter, model.Page{
|
||||
Number: 1,
|
||||
Size: uint32(CreationPhaseMapfixesLimit),
|
||||
},datastore.ListSortDisabled)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if CreationPhaseMapfixesLimit <= len(creation_mapfixes) {
|
||||
return nil, ErrCreationPhaseMapfixesLimit
|
||||
}
|
||||
}
|
||||
|
||||
// Check if TargetAssetID actually exists
|
||||
{
|
||||
_, err := svc.Client.Get(ctx, &maps.IdMessage{
|
||||
ID: request.TargetAssetID,
|
||||
})
|
||||
if err != nil {
|
||||
// TODO: match specific does not exist grpc error
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Check if too many operations have been created recently
|
||||
{
|
||||
count, err := svc.DB.Operations().CountSince(ctx,
|
||||
int64(userId),
|
||||
time.Now().Add(-CreateMapfixRecencyWindow),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if CreateMapfixRateLimit < count {
|
||||
return nil, ErrCreateMapfixRateLimit
|
||||
}
|
||||
}
|
||||
|
||||
operation, err := svc.DB.Operations().Create(ctx, model.Operation{
|
||||
Owner: userId,
|
||||
StatusID: model.OperationStatusCreated,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
create_request := model.CreateMapfixRequest{
|
||||
OperationID: operation.ID,
|
||||
ModelID: ModelID,
|
||||
TargetAssetID: TargetAssetID,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(create_request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = svc.Nats.Publish("maptest.mapfixes.create", []byte(j))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.OperationID{
|
||||
OperationID: operation.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetMapfix implements getMapfix operation.
|
||||
//
|
||||
// Retrieve map with ID.
|
||||
//
|
||||
// GET /mapfixes/{MapfixID}
|
||||
func (svc *Service) GetMapfix(ctx context.Context, params api.GetMapfixParams) (*api.Mapfix, error) {
|
||||
mapfix, err := svc.DB.Mapfixes().Get(ctx, int64(params.MapfixID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &api.Mapfix{
|
||||
ID: mapfix.ID,
|
||||
DisplayName: mapfix.DisplayName,
|
||||
Creator: mapfix.Creator,
|
||||
GameID: uint32(mapfix.GameID),
|
||||
CreatedAt: mapfix.CreatedAt.Unix(),
|
||||
UpdatedAt: mapfix.UpdatedAt.Unix(),
|
||||
Submitter: mapfix.Submitter,
|
||||
AssetID: mapfix.AssetID,
|
||||
AssetVersion: mapfix.AssetVersion,
|
||||
Completed: mapfix.Completed,
|
||||
TargetAssetID: mapfix.TargetAssetID,
|
||||
StatusID: uint32(mapfix.StatusID),
|
||||
StatusMessage: mapfix.StatusMessage,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListMapfixes implements listMapfixes operation.
|
||||
//
|
||||
// Get list of mapfixes.
|
||||
//
|
||||
// GET /mapfixes
|
||||
func (svc *Service) ListMapfixes(ctx context.Context, params api.ListMapfixesParams) (*api.Mapfixes, error) {
|
||||
filter := datastore.Optional()
|
||||
|
||||
if params.DisplayName.IsSet(){
|
||||
filter.Add2("display_name", params.DisplayName.Value)
|
||||
}
|
||||
if params.Creator.IsSet(){
|
||||
filter.Add2("creator", params.Creator.Value)
|
||||
}
|
||||
if params.GameID.IsSet(){
|
||||
filter.AddPostgresInt32("game_id", params.GameID.Value)
|
||||
}
|
||||
if params.Submitter.IsSet(){
|
||||
filter.AddPostgresInt64("submitter", params.Submitter.Value)
|
||||
}
|
||||
if params.AssetID.IsSet(){
|
||||
filter.AddPostgresInt64("asset_id", params.AssetID.Value)
|
||||
}
|
||||
if params.TargetAssetID.IsSet(){
|
||||
filter.AddPostgresInt64("target_asset_id", params.TargetAssetID.Value)
|
||||
}
|
||||
if params.StatusID.IsSet(){
|
||||
filter.AddPostgresInt32("status_id", params.StatusID.Value)
|
||||
}
|
||||
|
||||
sort := datastore.ListSort(params.Sort.Or(uint32(datastore.ListSortDisabled)))
|
||||
|
||||
total, items, err := svc.DB.Mapfixes().ListWithTotal(ctx, filter, model.Page{
|
||||
Number: params.Page,
|
||||
Size: params.Limit,
|
||||
},sort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp api.Mapfixes
|
||||
resp.Total=total
|
||||
for _, item := range items {
|
||||
resp.Mapfixes = append(resp.Mapfixes, api.Mapfix{
|
||||
ID: item.ID,
|
||||
DisplayName: item.DisplayName,
|
||||
Creator: item.Creator,
|
||||
GameID: item.GameID,
|
||||
CreatedAt: item.CreatedAt.Unix(),
|
||||
UpdatedAt: item.UpdatedAt.Unix(),
|
||||
Submitter: item.Submitter,
|
||||
AssetID: item.AssetID,
|
||||
AssetVersion: item.AssetVersion,
|
||||
Completed: item.Completed,
|
||||
TargetAssetID: item.TargetAssetID,
|
||||
StatusID: uint32(item.StatusID),
|
||||
})
|
||||
}
|
||||
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// PatchMapfixCompleted implements patchMapfixCompleted operation.
|
||||
//
|
||||
// Retrieve map with ID.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/completed
|
||||
func (svc *Service) SetMapfixCompleted(ctx context.Context, params api.SetMapfixCompletedParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleMaptest()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// check if caller has MaptestGame role (request must originate from a maptest roblox game)
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMaptest
|
||||
}
|
||||
|
||||
pmap := datastore.Optional()
|
||||
pmap.Add("completed", true)
|
||||
return svc.DB.Mapfixes().Update(ctx, params.MapfixID, pmap)
|
||||
}
|
||||
|
||||
// UpdateMapfixModel implements patchMapfixModel operation.
|
||||
//
|
||||
// Update model following role restrictions.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/model
|
||||
func (svc *Service) UpdateMapfixModel(ctx context.Context, params api.UpdateMapfixModelParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
// read mapfix (this could be done with a transaction WHERE clause)
|
||||
mapfix, err := svc.DB.Mapfixes().Get(ctx, params.MapfixID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check if caller is the submitter
|
||||
has_role := userId == mapfix.Submitter
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNotSubmitter
|
||||
}
|
||||
|
||||
OldModelID := mapfix.AssetID
|
||||
OldModelVersion := mapfix.AssetVersion
|
||||
NewModelID := uint64(params.ModelID)
|
||||
NewModelVersion := uint64(params.ModelVersion)
|
||||
|
||||
// check if Status is ChangesRequested|Submitted|UnderConstruction
|
||||
pmap := datastore.Optional()
|
||||
pmap.Add("asset_id", NewModelID)
|
||||
pmap.Add("asset_version", NewModelVersion)
|
||||
//always reset completed when model changes
|
||||
pmap.Add("completed", false)
|
||||
err = svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusChangesRequested, model.MapfixStatusSubmitted, model.MapfixStatusUnderConstruction}, pmap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataChangeModel{
|
||||
OldModelID: OldModelID,
|
||||
OldModelVersion: OldModelVersion,
|
||||
NewModelID: NewModelID,
|
||||
NewModelVersion: NewModelVersion,
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeChangeModel,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionMapfixReject invokes actionMapfixReject operation.
|
||||
//
|
||||
// Role Reviewer changes status from Submitted -> Rejected.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reject
|
||||
func (svc *Service) ActionMapfixReject(ctx context.Context, params api.ActionMapfixRejectParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleMapfixReview()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapfixReview
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.MapfixStatusRejected
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err = svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusSubmitted}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionMapfixRequestChanges invokes actionMapfixRequestChanges operation.
|
||||
//
|
||||
// Role Reviewer changes status from Validated|Accepted|Submitted -> ChangesRequested.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/request-changes
|
||||
func (svc *Service) ActionMapfixRequestChanges(ctx context.Context, params api.ActionMapfixRequestChangesParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleMapfixReview()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapfixReview
|
||||
}
|
||||
|
||||
// transaction
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.MapfixStatusChangesRequested)
|
||||
return svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidated, model.MapfixStatusAcceptedUnvalidated, model.MapfixStatusSubmitted}, smap)
|
||||
}
|
||||
|
||||
// ActionMapfixRevoke invokes actionMapfixRevoke operation.
|
||||
//
|
||||
// Role Submitter changes status from Submitted|ChangesRequested -> UnderConstruction.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/revoke
|
||||
func (svc *Service) ActionMapfixRevoke(ctx context.Context, params api.ActionMapfixRevokeParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
// read mapfix (this could be done with a transaction WHERE clause)
|
||||
mapfix, err := svc.DB.Mapfixes().Get(ctx, params.MapfixID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check if caller is the submitter
|
||||
has_role := userId == mapfix.Submitter
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNotSubmitter
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.MapfixStatusUnderConstruction
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err = svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusSubmitted, model.MapfixStatusChangesRequested}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerSubmit invokes actionMapfixTriggerSubmit operation.
|
||||
//
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-submit
|
||||
func (svc *Service) ActionMapfixTriggerSubmit(ctx context.Context, params api.ActionMapfixTriggerSubmitParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
// read mapfix (this could be done with a transaction WHERE clause)
|
||||
mapfix, err := svc.DB.Mapfixes().Get(ctx, params.MapfixID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check if caller is the submitter
|
||||
has_role := userId == mapfix.Submitter
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNotSubmitter
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.MapfixStatusSubmitted
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err = svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusUnderConstruction, model.MapfixStatusChangesRequested}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionMapfixResetSubmitting implements actionMapfixResetSubmitting operation.
|
||||
//
|
||||
// Role MapfixReview changes status from Submitting -> UnderConstruction.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-submitting
|
||||
func (svc *Service) ActionMapfixResetSubmitting(ctx context.Context, params api.ActionMapfixResetSubmittingParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check when mapfix was updated
|
||||
mapfix, err := svc.DB.Mapfixes().Get(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
|
||||
}
|
||||
|
||||
// check if caller has required role
|
||||
has_role := userId == mapfix.Submitter
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNotSubmitter
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.MapfixStatusUnderConstruction
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
smap.Add("status_message", "Manually forced reset")
|
||||
err = svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusSubmitting}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerUpload invokes actionMapfixTriggerUpload operation.
|
||||
//
|
||||
// Role Admin changes status from Validated -> Uploading.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-upload
|
||||
func (svc *Service) ActionMapfixTriggerUpload(ctx context.Context, params api.ActionMapfixTriggerUploadParams) 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.MapfixStatusUploading
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
mapfix, err := svc.DB.Mapfixes().IfStatusThenUpdateAndGet(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidated}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// this is a map fix
|
||||
upload_fix_request := model.UploadMapfixRequest{
|
||||
MapfixID: mapfix.ID,
|
||||
ModelID: mapfix.ValidatedAssetID,
|
||||
ModelVersion: mapfix.ValidatedAssetVersion,
|
||||
TargetAssetID: mapfix.TargetAssetID,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(upload_fix_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.Nats.Publish("maptest.mapfixes.upload", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionMapfixValidate invokes actionMapfixValidate operation.
|
||||
//
|
||||
// Role MapfixRelease changes status from Uploading -> Validated.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-uploading
|
||||
func (svc *Service) ActionMapfixValidated(ctx context.Context, params api.ActionMapfixValidatedParams) 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.DB.Mapfixes().Get(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.MapfixStatusValidated
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err = svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusUploading}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionMapfixTriggerValidate invokes actionMapfixTriggerValidate operation.
|
||||
//
|
||||
// Role Reviewer triggers validation and changes status from Submitted -> Validating.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/trigger-validate
|
||||
func (svc *Service) ActionMapfixTriggerValidate(ctx context.Context, params api.ActionMapfixTriggerValidateParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleMapfixReview()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapfixReview
|
||||
}
|
||||
|
||||
// read mapfix (this could be done with a transaction WHERE clause)
|
||||
mapfix, err := svc.DB.Mapfixes().Get(ctx, params.MapfixID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check if caller is NOT the submitter
|
||||
has_role = userId == mapfix.Submitter
|
||||
if has_role {
|
||||
return ErrAcceptOwnMapfix
|
||||
}
|
||||
|
||||
// Check if an active mapfix with the same target asset id exists
|
||||
if mapfix.TargetAssetID != 0 {
|
||||
filter := datastore.Optional()
|
||||
filter.Add("target_asset_id", mapfix.TargetAssetID)
|
||||
filter.Add("status_id", ActiveAcceptedMapfixStatuses)
|
||||
active_mapfixes, err := svc.DB.Mapfixes().List(ctx, filter, model.Page{
|
||||
Number: 1,
|
||||
Size: 1,
|
||||
},datastore.ListSortDisabled)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(active_mapfixes) != 0{
|
||||
return ErrActiveMapfixSameTargetAssetID
|
||||
}
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.MapfixStatusValidating
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
mapfix, err = svc.DB.Mapfixes().IfStatusThenUpdateAndGet(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusSubmitted}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
validate_request := model.ValidateMapfixRequest{
|
||||
MapfixID: mapfix.ID,
|
||||
ModelID: mapfix.AssetID,
|
||||
ModelVersion: mapfix.AssetVersion,
|
||||
ValidatedModelID: nil,
|
||||
}
|
||||
|
||||
// sentinel values because we're not using rust
|
||||
if mapfix.ValidatedAssetID != 0 {
|
||||
validate_request.ValidatedModelID = &mapfix.ValidatedAssetID
|
||||
}
|
||||
|
||||
j, err := json.Marshal(validate_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.Nats.Publish("maptest.mapfixes.validate", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionMapfixRetryValidate invokes actionMapfixRetryValidate operation.
|
||||
//
|
||||
// Role Reviewer re-runs validation and changes status from Accepted -> Validating.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/retry-validate
|
||||
func (svc *Service) ActionMapfixRetryValidate(ctx context.Context, params api.ActionMapfixRetryValidateParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleMapfixReview()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapfixReview
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.MapfixStatusValidating
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
mapfix, err := svc.DB.Mapfixes().IfStatusThenUpdateAndGet(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusAcceptedUnvalidated}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
validate_request := model.ValidateMapfixRequest{
|
||||
MapfixID: mapfix.ID,
|
||||
ModelID: mapfix.AssetID,
|
||||
ModelVersion: mapfix.AssetVersion,
|
||||
ValidatedModelID: nil,
|
||||
}
|
||||
|
||||
// sentinel values because we're not using rust
|
||||
if mapfix.ValidatedAssetID != 0 {
|
||||
validate_request.ValidatedModelID = &mapfix.ValidatedAssetID
|
||||
}
|
||||
|
||||
j, err := json.Marshal(validate_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.Nats.Publish("maptest.mapfixes.validate", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionMapfixAccepted implements actionMapfixAccepted operation.
|
||||
//
|
||||
// Role MapfixReview changes status from Validating -> Accepted.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/reset-validating
|
||||
func (svc *Service) ActionMapfixAccepted(ctx context.Context, params api.ActionMapfixAcceptedParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleMapfixReview()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapfixReview
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check when mapfix was updated
|
||||
mapfix, err := svc.DB.Mapfixes().Get(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.MapfixStatusAcceptedUnvalidated
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
smap.Add("status_message", "Manually forced reset")
|
||||
err = svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
73
pkg/service/maps.go
Normal file
73
pkg/service/maps.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/go-grpc/maps"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
)
|
||||
|
||||
// ListMaps implements listMaps operation.
|
||||
//
|
||||
// Get list of maps.
|
||||
//
|
||||
// GET /maps
|
||||
func (svc *Service) ListMaps(ctx context.Context, params api.ListMapsParams) ([]api.Map, error) {
|
||||
filter := maps.MapFilter{}
|
||||
|
||||
if params.DisplayName.IsSet(){
|
||||
filter.DisplayName = ¶ms.DisplayName.Value
|
||||
}
|
||||
if params.Creator.IsSet(){
|
||||
filter.Creator = ¶ms.Creator.Value
|
||||
}
|
||||
if params.GameID.IsSet(){
|
||||
filter.GameID = ¶ms.GameID.Value
|
||||
}
|
||||
|
||||
mapList, err := svc.Client.List(ctx, &maps.ListRequest{
|
||||
Filter: &filter,
|
||||
Page: &maps.Pagination{
|
||||
Size: params.Limit,
|
||||
Number: params.Page,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []api.Map
|
||||
for _, item := range mapList.Maps {
|
||||
resp = append(resp, api.Map{
|
||||
ID: item.ID,
|
||||
DisplayName: item.DisplayName,
|
||||
Creator: item.Creator,
|
||||
GameID: item.GameID,
|
||||
Date: item.Date,
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetMap implements getScript operation.
|
||||
//
|
||||
// Get the specified script by ID.
|
||||
//
|
||||
// GET /maps/{MapID}
|
||||
func (svc *Service) GetMap(ctx context.Context, params api.GetMapParams) (*api.Map, error) {
|
||||
mapResponse, err := svc.Client.Get(ctx, &maps.IdMessage{
|
||||
ID: params.MapID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.Map{
|
||||
ID: mapResponse.ID,
|
||||
DisplayName: mapResponse.DisplayName,
|
||||
Creator: mapResponse.Creator,
|
||||
GameID: mapResponse.GameID,
|
||||
Date: mapResponse.Date,
|
||||
}, nil
|
||||
}
|
||||
46
pkg/service/operations.go
Normal file
46
pkg/service/operations.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
)
|
||||
|
||||
// GetOperation implements getOperation operation.
|
||||
//
|
||||
// Get the specified operation by ID.
|
||||
//
|
||||
// GET /operations/{OperationID}
|
||||
func (svc *Service) GetOperation(ctx context.Context, params api.GetOperationParams) (*api.Operation, error) {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return nil, ErrUserInfo
|
||||
}
|
||||
|
||||
// You must be the operation owner to read it
|
||||
|
||||
operation, err := svc.DB.Operations().Get(ctx, params.OperationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check if caller is the submitter
|
||||
has_role := userId == operation.Owner
|
||||
if !has_role {
|
||||
return nil, ErrPermissionDeniedNotSubmitter
|
||||
}
|
||||
|
||||
return &api.Operation{
|
||||
OperationID: operation.ID,
|
||||
Date: operation.CreatedAt.Unix(),
|
||||
Owner: int64(operation.Owner),
|
||||
Status: int32(operation.StatusID),
|
||||
StatusMessage: operation.StatusMessage,
|
||||
Path: operation.Path,
|
||||
}, nil
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
// Create a new script policy.
|
||||
//
|
||||
// POST /script-policy
|
||||
func (svc *Service) CreateScriptPolicy(ctx context.Context, req *api.ScriptPolicyCreate) (*api.ID, error) {
|
||||
func (svc *Service) CreateScriptPolicy(ctx context.Context, req *api.ScriptPolicyCreate) (*api.ScriptPolicyID, error) {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return nil, ErrUserInfo
|
||||
@@ -44,8 +44,8 @@ func (svc *Service) CreateScriptPolicy(ctx context.Context, req *api.ScriptPolic
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.ID{
|
||||
ID: script.ID,
|
||||
return &api.ScriptPolicyID{
|
||||
ScriptPolicyID: script.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -63,13 +63,13 @@ func (svc *Service) ListScriptPolicy(ctx context.Context, params api.ListScriptP
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filter.AddNotNil("from_script_hash", int64(hash)) // No type safety!
|
||||
filter.Add("from_script_hash", int64(hash)) // No type safety!
|
||||
}
|
||||
if params.ToScriptID.IsSet(){
|
||||
filter.AddNotNil("to_script_id", params.ToScriptID.Value)
|
||||
filter.Add("to_script_id", params.ToScriptID.Value)
|
||||
}
|
||||
if params.Policy.IsSet(){
|
||||
filter.AddNotNil("policy", params.Policy.Value)
|
||||
filter.Add("policy", params.Policy.Value)
|
||||
}
|
||||
|
||||
items, err := svc.DB.ScriptPolicy().List(ctx, filter, model.Page{
|
||||
@@ -121,13 +121,6 @@ func (svc *Service) DeleteScriptPolicy(ctx context.Context, params api.DeleteScr
|
||||
//
|
||||
// GET /script-policy/{ScriptPolicyID}
|
||||
func (svc *Service) GetScriptPolicy(ctx context.Context, params api.GetScriptPolicyParams) (*api.ScriptPolicy, error) {
|
||||
_, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return nil, ErrUserInfo
|
||||
}
|
||||
|
||||
// Read permission for script policy only requires you to be logged in
|
||||
|
||||
policy, err := svc.DB.ScriptPolicy().Get(ctx, params.ScriptPolicyID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
// Create a new script.
|
||||
//
|
||||
// POST /scripts
|
||||
func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*api.ID, error) {
|
||||
func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*api.ScriptID, error) {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return nil, ErrUserInfo
|
||||
@@ -39,8 +39,8 @@ func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*a
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.ID{
|
||||
ID: script.ID,
|
||||
return &api.ScriptID{
|
||||
ScriptID: script.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -57,16 +57,19 @@ func (svc *Service) ListScripts(ctx context.Context, params api.ListScriptsParam
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filter.AddNotNil("hash", int64(hash)) // No type safety!
|
||||
filter.Add("hash", int64(hash)) // No type safety!
|
||||
}
|
||||
if params.Name.IsSet(){
|
||||
filter.AddNotNil("name", params.Name.Value)
|
||||
filter.Add("name", params.Name.Value)
|
||||
}
|
||||
if params.Source.IsSet(){
|
||||
filter.AddNotNil("source", params.Source.Value)
|
||||
filter.Add("source", params.Source.Value)
|
||||
}
|
||||
if params.SubmissionID.IsSet(){
|
||||
filter.AddNotNil("submission_id", params.SubmissionID.Value)
|
||||
if params.ResourceType.IsSet(){
|
||||
filter.Add("resource_type", params.ResourceType.Value)
|
||||
}
|
||||
if params.ResourceID.IsSet(){
|
||||
filter.Add("resource_id", params.ResourceID.Value)
|
||||
}
|
||||
|
||||
items, err := svc.DB.Scripts().List(ctx, filter, model.Page{
|
||||
@@ -119,13 +122,6 @@ func (svc *Service) DeleteScript(ctx context.Context, params api.DeleteScriptPar
|
||||
//
|
||||
// GET /scripts/{ScriptID}
|
||||
func (svc *Service) GetScript(ctx context.Context, params api.GetScriptParams) (*api.Script, error) {
|
||||
_, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return nil, ErrUserInfo
|
||||
}
|
||||
|
||||
// Read permission for scripts only requires you to be logged in
|
||||
|
||||
script, err := svc.DB.Scripts().Get(ctx, params.ScriptID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -17,10 +17,12 @@ var (
|
||||
// Submissions roles bitflag
|
||||
type Roles int32
|
||||
var (
|
||||
RolesSubmissionUpload Roles = 1<<6
|
||||
RolesSubmissionReview Roles = 1<<5
|
||||
RolesSubmissionRelease Roles = 1<<4
|
||||
RolesScriptWrite Roles = 1<<3
|
||||
RolesMapUpload Roles = 1<<2
|
||||
RolesMapReview Roles = 1<<1
|
||||
RolesMapfixUpload Roles = 1<<2
|
||||
RolesMapfixReview Roles = 1<<1
|
||||
RolesMapDownload Roles = 1<<0
|
||||
RolesEmpty Roles = 0
|
||||
)
|
||||
@@ -32,13 +34,13 @@ var (
|
||||
RoleQuat GroupRole = 255
|
||||
RoleItzaname GroupRole = 254
|
||||
RoleStagingDeveloper GroupRole = 240
|
||||
RolesAll Roles = RolesScriptWrite|RolesSubmissionRelease|RolesMapUpload|RolesMapReview|RolesMapDownload
|
||||
RolesAll Roles = ^RolesEmpty
|
||||
// has SubmissionUpload
|
||||
RoleMapAdmin GroupRole = 128
|
||||
RolesMapAdmin Roles = RolesSubmissionRelease|RolesMapUpload|RolesMapReview|RolesMapDownload
|
||||
// has SubmissionReview
|
||||
RolesMapAdmin Roles = RolesSubmissionRelease|RolesSubmissionUpload|RolesSubmissionReview|RolesMapCouncil
|
||||
// has MapfixReview
|
||||
RoleMapCouncil GroupRole = 64
|
||||
RolesMapCouncil Roles = RolesMapReview|RolesMapUpload|RolesMapDownload
|
||||
RolesMapCouncil Roles = RolesMapfixReview|RolesMapfixUpload|RolesMapAccess
|
||||
// access to downloading maps
|
||||
RoleMapAccess GroupRole = 32
|
||||
RolesMapAccess Roles = RolesMapDownload
|
||||
@@ -86,13 +88,6 @@ func (usr UserInfoHandle) Validate() (bool, error) {
|
||||
}
|
||||
return validate.Valid, nil
|
||||
}
|
||||
func (usr UserInfoHandle) IsSubmitter(submitter uint64) (bool, error) {
|
||||
userId, err := usr.GetUserID()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return userId == submitter, nil
|
||||
}
|
||||
func (usr UserInfoHandle) hasRoles(wantRoles Roles) (bool, error) {
|
||||
haveroles, err := usr.GetRoles()
|
||||
if err != nil {
|
||||
@@ -129,10 +124,10 @@ func (usr UserInfoHandle) GetRoles() (Roles, error) {
|
||||
|
||||
// RoleThumbnail
|
||||
func (usr UserInfoHandle) HasRoleMapfixUpload() (bool, error) {
|
||||
return usr.hasRoles(RolesMapUpload)
|
||||
return usr.hasRoles(RolesMapfixUpload)
|
||||
}
|
||||
func (usr UserInfoHandle) HasRoleMapfixReview() (bool, error) {
|
||||
return usr.hasRoles(RolesMapReview)
|
||||
return usr.hasRoles(RolesMapfixReview)
|
||||
}
|
||||
func (usr UserInfoHandle) HasRoleMapDownload() (bool, error) {
|
||||
return usr.hasRoles(RolesMapDownload)
|
||||
@@ -141,10 +136,10 @@ func (usr UserInfoHandle) HasRoleSubmissionRelease() (bool, error) {
|
||||
return usr.hasRoles(RolesSubmissionRelease)
|
||||
}
|
||||
func (usr UserInfoHandle) HasRoleSubmissionUpload() (bool, error) {
|
||||
return usr.hasRoles(RolesMapUpload)
|
||||
return usr.hasRoles(RolesSubmissionUpload)
|
||||
}
|
||||
func (usr UserInfoHandle) HasRoleSubmissionReview() (bool, error) {
|
||||
return usr.hasRoles(RolesMapReview)
|
||||
return usr.hasRoles(RolesSubmissionReview)
|
||||
}
|
||||
func (usr UserInfoHandle) HasRoleScriptWrite() (bool, error) {
|
||||
return usr.hasRoles(RolesScriptWrite)
|
||||
|
||||
@@ -19,11 +19,14 @@ var (
|
||||
ErrDelayReset = errors.New("Please give the validator at least 10 seconds to operate before attempting to reset the status")
|
||||
ErrPermissionDeniedNotSubmitter = fmt.Errorf("%w: You must be the submitter to perform this action", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleSubmissionRelease = fmt.Errorf("%w: Need Role SubmissionRelease", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMapUpload = fmt.Errorf("%w: Need Role MapUpload", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMapReview = fmt.Errorf("%w: Need Role MapReview", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMapfixUpload = fmt.Errorf("%w: Need Role MapfixUpload", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMapfixReview = fmt.Errorf("%w: Need Role MapfixReview", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleSubmissionUpload = fmt.Errorf("%w: Need Role SubmissionUpload", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleSubmissionReview = fmt.Errorf("%w: Need Role SubmissionReview", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMapDownload = fmt.Errorf("%w: Need Role MapDownload", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleScriptWrite = fmt.Errorf("%w: Need Role ScriptWrite", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMaptest = fmt.Errorf("%w: Need Role Maptest", ErrPermissionDenied)
|
||||
ErrNegativeID = errors.New("A negative ID was provided")
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
|
||||
@@ -20,36 +20,35 @@ var(
|
||||
model.SubmissionStatusSubmitted,
|
||||
model.SubmissionStatusUnderConstruction,
|
||||
}
|
||||
// prevent two mapfixes with same asset id
|
||||
ActiveSubmissionStatuses = []model.SubmissionStatus{
|
||||
model.SubmissionStatusUploading,
|
||||
model.SubmissionStatusValidated,
|
||||
model.SubmissionStatusValidating,
|
||||
model.SubmissionStatusAccepted,
|
||||
model.SubmissionStatusChangesRequested,
|
||||
model.SubmissionStatusSubmitted,
|
||||
model.SubmissionStatusUnderConstruction,
|
||||
}
|
||||
// limit mapfixes in the pipeline to one per target map
|
||||
ActiveAcceptedSubmissionStatuses = []model.SubmissionStatus{
|
||||
model.SubmissionStatusUploading,
|
||||
model.SubmissionStatusValidated,
|
||||
model.SubmissionStatusValidating,
|
||||
model.SubmissionStatusAccepted,
|
||||
model.SubmissionStatusAcceptedUnvalidated,
|
||||
}
|
||||
// Allow 5 submissions every 10 minutes
|
||||
CreateSubmissionRateLimit int64 = 5
|
||||
CreateSubmissionRecencyWindow = time.Second*600
|
||||
)
|
||||
|
||||
var (
|
||||
ErrCreationPhaseSubmissionsLimit = errors.New("Active submissions limited to 20")
|
||||
ErrActiveSubmissionSameAssetID = errors.New("There is an active submission with the same AssetID")
|
||||
ErrUploadedAssetIDAlreadyExists = errors.New("The submission UploadedAssetID is already set")
|
||||
ErrReleaseInvalidStatus = errors.New("Only submissions with Uploaded status can be released")
|
||||
ErrReleaseNoUploadedAssetID = errors.New("Only submissions with a UploadedAssetID can be released")
|
||||
ErrAcceptOwnSubmission = fmt.Errorf("%w: You cannot accept your own submission as the submitter", ErrPermissionDenied)
|
||||
ErrCreateSubmissionRateLimit = errors.New("You must not create more than 5 submissions every 10 minutes")
|
||||
)
|
||||
|
||||
// POST /submissions
|
||||
func (svc *Service) CreateSubmission(ctx context.Context, request *api.SubmissionCreate) (*api.ID, error) {
|
||||
func (svc *Service) CreateSubmission(ctx context.Context, request *api.SubmissionTriggerCreate) (*api.OperationID, error) {
|
||||
// sanitization
|
||||
if request.AssetID<0{
|
||||
return nil, ErrNegativeID
|
||||
}
|
||||
var ModelID=uint64(request.AssetID);
|
||||
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return nil, ErrUserInfo
|
||||
@@ -78,40 +77,46 @@ func (svc *Service) CreateSubmission(ctx context.Context, request *api.Submissio
|
||||
}
|
||||
}
|
||||
|
||||
// Check if an active submission with the same asset id exists
|
||||
// Check if too many operations have been created recently
|
||||
{
|
||||
filter := datastore.Optional()
|
||||
filter.Add("asset_id", request.AssetID)
|
||||
filter.Add("asset_version", request.AssetVersion)
|
||||
filter.Add("status_id", ActiveSubmissionStatuses)
|
||||
active_submissions, err := svc.DB.Submissions().List(ctx, filter, model.Page{
|
||||
Number: 1,
|
||||
Size: 1,
|
||||
},datastore.ListSortDisabled)
|
||||
count, err := svc.DB.Operations().CountSince(ctx,
|
||||
int64(userId),
|
||||
time.Now().Add(-CreateSubmissionRecencyWindow),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(active_submissions) != 0{
|
||||
return nil, ErrActiveSubmissionSameAssetID
|
||||
|
||||
if CreateSubmissionRateLimit < count {
|
||||
return nil, ErrCreateSubmissionRateLimit
|
||||
}
|
||||
}
|
||||
|
||||
submission, err := svc.DB.Submissions().Create(ctx, model.Submission{
|
||||
ID: 0,
|
||||
DisplayName: request.DisplayName,
|
||||
Creator: request.Creator,
|
||||
GameID: request.GameID,
|
||||
Submitter: int64(userId),
|
||||
AssetID: request.AssetID,
|
||||
AssetVersion: request.AssetVersion,
|
||||
Completed: false,
|
||||
StatusID: model.SubmissionStatusUnderConstruction,
|
||||
operation, err := svc.DB.Operations().Create(ctx, model.Operation{
|
||||
Owner: userId,
|
||||
StatusID: model.OperationStatusCreated,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &api.ID{
|
||||
ID: submission.ID,
|
||||
|
||||
create_request := model.CreateSubmissionRequest{
|
||||
OperationID: operation.ID,
|
||||
ModelID: ModelID,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(create_request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = svc.Nats.Publish("maptest.submissions.create", []byte(j))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.OperationID{
|
||||
OperationID: operation.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -129,7 +134,7 @@ func (svc *Service) GetSubmission(ctx context.Context, params api.GetSubmissionP
|
||||
ID: submission.ID,
|
||||
DisplayName: submission.DisplayName,
|
||||
Creator: submission.Creator,
|
||||
GameID: submission.GameID,
|
||||
GameID: int32(submission.GameID),
|
||||
CreatedAt: submission.CreatedAt.Unix(),
|
||||
UpdatedAt: submission.UpdatedAt.Unix(),
|
||||
Submitter: int64(submission.Submitter),
|
||||
@@ -147,7 +152,7 @@ func (svc *Service) GetSubmission(ctx context.Context, params api.GetSubmissionP
|
||||
// Get list of submissions.
|
||||
//
|
||||
// GET /submissions
|
||||
func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissionsParams) ([]api.Submission, error) {
|
||||
func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissionsParams) (*api.Submissions, error) {
|
||||
filter := datastore.Optional()
|
||||
|
||||
if params.DisplayName.IsSet(){
|
||||
@@ -159,10 +164,22 @@ func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissi
|
||||
if params.GameID.IsSet(){
|
||||
filter.Add("game_id", params.GameID.Value)
|
||||
}
|
||||
if params.Submitter.IsSet(){
|
||||
filter.Add("submitter", params.Submitter.Value)
|
||||
}
|
||||
if params.AssetID.IsSet(){
|
||||
filter.Add("asset_id", params.AssetID.Value)
|
||||
}
|
||||
if params.UploadedAssetID.IsSet(){
|
||||
filter.Add("uploaded_asset_id", params.UploadedAssetID.Value)
|
||||
}
|
||||
if params.StatusID.IsSet(){
|
||||
filter.Add("status_id", params.StatusID.Value)
|
||||
}
|
||||
|
||||
sort := datastore.ListSort(params.Sort.Or(int32(datastore.ListSortDisabled)))
|
||||
|
||||
items, err := svc.DB.Submissions().List(ctx, filter, model.Page{
|
||||
total, items, err := svc.DB.Submissions().ListWithTotal(ctx, filter, model.Page{
|
||||
Number: params.Page,
|
||||
Size: params.Limit,
|
||||
},sort)
|
||||
@@ -170,13 +187,14 @@ func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissi
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []api.Submission
|
||||
var resp api.Submissions
|
||||
resp.Total=total
|
||||
for _, item := range items {
|
||||
resp = append(resp, api.Submission{
|
||||
resp.Submissions = append(resp.Submissions, api.Submission{
|
||||
ID: item.ID,
|
||||
DisplayName: item.DisplayName,
|
||||
Creator: item.Creator,
|
||||
GameID: item.GameID,
|
||||
GameID: int32(item.GameID),
|
||||
CreatedAt: item.CreatedAt.Unix(),
|
||||
UpdatedAt: item.UpdatedAt.Unix(),
|
||||
Submitter: int64(item.Submitter),
|
||||
@@ -188,7 +206,7 @@ func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissi
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// PatchSubmissionCompleted implements patchSubmissionCompleted operation.
|
||||
@@ -233,22 +251,58 @@ func (svc *Service) UpdateSubmissionModel(ctx context.Context, params api.Update
|
||||
return err
|
||||
}
|
||||
|
||||
has_role, err := userInfo.IsSubmitter(uint64(submission.Submitter))
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check if caller is the submitter
|
||||
has_role := userId == submission.Submitter
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNotSubmitter
|
||||
}
|
||||
|
||||
OldModelID := submission.AssetID
|
||||
OldModelVersion := submission.AssetVersion
|
||||
NewModelID := uint64(params.ModelID)
|
||||
NewModelVersion := uint64(params.ModelVersion)
|
||||
|
||||
// check if Status is ChangesRequested|Submitted|UnderConstruction
|
||||
pmap := datastore.Optional()
|
||||
pmap.AddNotNil("asset_id", params.ModelID)
|
||||
pmap.AddNotNil("asset_version", params.VersionID)
|
||||
pmap.Add("asset_id", NewModelID)
|
||||
pmap.Add("asset_version", NewModelVersion)
|
||||
//always reset completed when model changes
|
||||
pmap.Add("completed", false)
|
||||
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusChangesRequested, model.SubmissionStatusSubmitted, model.SubmissionStatusUnderConstruction}, pmap)
|
||||
err = svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusChangesRequested, model.SubmissionStatusUnderConstruction}, pmap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataChangeModel{
|
||||
OldModelID: OldModelID,
|
||||
OldModelVersion: OldModelVersion,
|
||||
NewModelID: NewModelID,
|
||||
NewModelVersion: NewModelVersion,
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: submission.ID,
|
||||
EventType: model.AuditEventTypeChangeModel,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionSubmissionReject invokes actionSubmissionReject operation.
|
||||
@@ -268,13 +322,45 @@ func (svc *Service) ActionSubmissionReject(ctx context.Context, params api.Actio
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapReview
|
||||
return ErrPermissionDeniedNeedRoleSubmissionReview
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusRejected
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.SubmissionStatusRejected)
|
||||
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitted}, smap)
|
||||
smap.Add("status_id", target_status)
|
||||
err = svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitted}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionSubmissionRequestChanges invokes actionSubmissionRequestChanges operation.
|
||||
@@ -294,13 +380,45 @@ func (svc *Service) ActionSubmissionRequestChanges(ctx context.Context, params a
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapReview
|
||||
return ErrPermissionDeniedNeedRoleSubmissionReview
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusChangesRequested
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.SubmissionStatusChangesRequested)
|
||||
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidated, model.SubmissionStatusAccepted, model.SubmissionStatusSubmitted}, smap)
|
||||
smap.Add("status_id", target_status)
|
||||
err = svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidated, model.SubmissionStatusAcceptedUnvalidated, model.SubmissionStatusSubmitted}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionSubmissionRevoke invokes actionSubmissionRevoke operation.
|
||||
@@ -320,27 +438,56 @@ func (svc *Service) ActionSubmissionRevoke(ctx context.Context, params api.Actio
|
||||
return err
|
||||
}
|
||||
|
||||
has_role, err := userInfo.IsSubmitter(uint64(submission.Submitter))
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check if caller is the submitter
|
||||
has_role := userId == submission.Submitter
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNotSubmitter
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusUnderConstruction
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.SubmissionStatusUnderConstruction)
|
||||
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitted, model.SubmissionStatusChangesRequested}, smap)
|
||||
smap.Add("status_id", target_status)
|
||||
err = svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitted, model.SubmissionStatusChangesRequested}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionSubmissionSubmit invokes actionSubmissionSubmit operation.
|
||||
// ActionSubmissionTriggerSubmit invokes actionSubmissionTriggerSubmit operation.
|
||||
//
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitted.
|
||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/submit
|
||||
func (svc *Service) ActionSubmissionSubmit(ctx context.Context, params api.ActionSubmissionSubmitParams) error {
|
||||
// POST /submissions/{SubmissionID}/status/trigger-submit
|
||||
func (svc *Service) ActionSubmissionTriggerSubmit(ctx context.Context, params api.ActionSubmissionTriggerSubmitParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
@@ -352,19 +499,114 @@ func (svc *Service) ActionSubmissionSubmit(ctx context.Context, params api.Actio
|
||||
return err
|
||||
}
|
||||
|
||||
has_role, err := userInfo.IsSubmitter(uint64(submission.Submitter))
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check if caller is the submitter
|
||||
has_role := userId == submission.Submitter
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNotSubmitter
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusSubmitted
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.SubmissionStatusSubmitted)
|
||||
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusUnderConstruction, model.SubmissionStatusChangesRequested}, smap)
|
||||
smap.Add("status_id", target_status)
|
||||
err = svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusUnderConstruction, model.SubmissionStatusChangesRequested}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionSubmissionResetSubmitting implements actionSubmissionResetSubmitting operation.
|
||||
//
|
||||
// Role SubmissionReview changes status from Submitting -> UnderConstruction.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/reset-submitting
|
||||
func (svc *Service) ActionSubmissionResetSubmitting(ctx context.Context, params api.ActionSubmissionResetSubmittingParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check when submission was updated
|
||||
submission, err := svc.DB.Submissions().Get(ctx, params.SubmissionID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if time.Now().Before(submission.UpdatedAt.Add(time.Second*10)) {
|
||||
// the last time the submission was updated must be longer than 10 seconds ago
|
||||
return ErrDelayReset
|
||||
}
|
||||
|
||||
// check if caller has required role
|
||||
has_role := userId == submission.Submitter
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNotSubmitter
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusUnderConstruction
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
smap.Add("status_message", "Manually forced reset")
|
||||
err = svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitting}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionSubmissionTriggerUpload invokes actionSubmissionTriggerUpload operation.
|
||||
@@ -384,12 +626,18 @@ func (svc *Service) ActionSubmissionTriggerUpload(ctx context.Context, params ap
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapUpload
|
||||
return ErrPermissionDeniedNeedRoleSubmissionUpload
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusUploading
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.SubmissionStatusUploading)
|
||||
smap.Add("status_id", target_status)
|
||||
submission, err := svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidated}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -398,7 +646,7 @@ func (svc *Service) ActionSubmissionTriggerUpload(ctx context.Context, params ap
|
||||
// sentinel value because we are not using rust
|
||||
if submission.UploadedAssetID == 0 {
|
||||
// this is a new map
|
||||
upload_new_request := model.UploadNewRequest{
|
||||
upload_new_request := model.UploadSubmissionRequest{
|
||||
SubmissionID: submission.ID,
|
||||
ModelID: submission.ValidatedAssetID,
|
||||
ModelVersion: submission.ValidatedAssetVersion,
|
||||
@@ -411,12 +659,36 @@ func (svc *Service) ActionSubmissionTriggerUpload(ctx context.Context, params ap
|
||||
return err
|
||||
}
|
||||
|
||||
svc.Nats.Publish("maptest.submissions.upload", []byte(j))
|
||||
_, err = svc.Nats.Publish("maptest.submissions.upload", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// refuse to operate
|
||||
return ErrUploadedAssetIDAlreadyExists
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -437,7 +709,12 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params api.Ac
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapUpload
|
||||
return ErrPermissionDeniedNeedRoleSubmissionUpload
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check when submission was updated
|
||||
@@ -451,9 +728,36 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params api.Ac
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusValidated
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.SubmissionStatusValidated)
|
||||
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusUploading}, smap)
|
||||
smap.Add("status_id", target_status)
|
||||
err = svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusUploading}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionSubmissionTriggerValidate invokes actionSubmissionTriggerValidate operation.
|
||||
@@ -473,7 +777,7 @@ func (svc *Service) ActionSubmissionTriggerValidate(ctx context.Context, params
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapReview
|
||||
return ErrPermissionDeniedNeedRoleSubmissionReview
|
||||
}
|
||||
|
||||
// read submission (this could be done with a transaction WHERE clause)
|
||||
@@ -482,24 +786,27 @@ func (svc *Service) ActionSubmissionTriggerValidate(ctx context.Context, params
|
||||
return err
|
||||
}
|
||||
|
||||
has_role, err = userInfo.IsSubmitter(uint64(submission.Submitter))
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check if caller is NOT the submitter
|
||||
has_role = userId == submission.Submitter
|
||||
if has_role {
|
||||
return ErrAcceptOwnSubmission
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusValidating
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.SubmissionStatusValidating)
|
||||
smap.Add("status_id", target_status)
|
||||
submission, err = svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitted}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
validate_request := model.ValidateRequest{
|
||||
validate_request := model.ValidateSubmissionRequest{
|
||||
SubmissionID: submission.ID,
|
||||
ModelID: submission.AssetID,
|
||||
ModelVersion: submission.AssetVersion,
|
||||
@@ -516,7 +823,31 @@ func (svc *Service) ActionSubmissionTriggerValidate(ctx context.Context, params
|
||||
return err
|
||||
}
|
||||
|
||||
svc.Nats.Publish("maptest.submissions.validate", []byte(j))
|
||||
_, err = svc.Nats.Publish("maptest.submissions.validate", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -538,18 +869,24 @@ func (svc *Service) ActionSubmissionRetryValidate(ctx context.Context, params ap
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapReview
|
||||
return ErrPermissionDeniedNeedRoleSubmissionReview
|
||||
}
|
||||
|
||||
// transaction
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.SubmissionStatusValidating)
|
||||
submission, err := svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusAccepted}, smap)
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
validate_request := model.ValidateRequest{
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusValidating
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
submission, err := svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusAcceptedUnvalidated}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
validate_request := model.ValidateSubmissionRequest{
|
||||
SubmissionID: submission.ID,
|
||||
ModelID: submission.AssetID,
|
||||
ModelVersion: submission.AssetVersion,
|
||||
@@ -566,7 +903,31 @@ func (svc *Service) ActionSubmissionRetryValidate(ctx context.Context, params ap
|
||||
return err
|
||||
}
|
||||
|
||||
svc.Nats.Publish("maptest.submissions.validate", []byte(j))
|
||||
_, err = svc.Nats.Publish("maptest.submissions.validate", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -588,7 +949,12 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params api.Act
|
||||
}
|
||||
// check if caller has required role
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleMapReview
|
||||
return ErrPermissionDeniedNeedRoleSubmissionReview
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check when submission was updated
|
||||
@@ -602,10 +968,37 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params api.Act
|
||||
}
|
||||
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusAcceptedUnvalidated
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.SubmissionStatusAccepted)
|
||||
smap.Add("status_id", target_status)
|
||||
smap.Add("status_message", "Manually forced reset")
|
||||
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, smap)
|
||||
err = svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReleaseSubmissions invokes releaseSubmissions operation.
|
||||
@@ -651,12 +1044,13 @@ func (svc *Service) ReleaseSubmissions(ctx context.Context, request []api.Releas
|
||||
|
||||
for i,submission := range submissions{
|
||||
date := request[i].Date.Unix()
|
||||
var GameID = int32(submission.GameID)
|
||||
// create each map with go-grpc
|
||||
_, err := svc.Client.Create(ctx, &maps.MapRequest{
|
||||
ID: submission.UploadedAssetID,
|
||||
ID: int64(submission.UploadedAssetID),
|
||||
DisplayName: &submission.DisplayName,
|
||||
Creator: &submission.Creator,
|
||||
GameID: &submission.GameID,
|
||||
GameID: &GameID,
|
||||
Date: &date,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
280
pkg/service_internal/mapfixes.go
Normal file
280
pkg/service_internal/mapfixes.go
Normal file
@@ -0,0 +1,280 @@
|
||||
package service_internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
var(
|
||||
// prevent two mapfixes with same asset id
|
||||
ActiveMapfixStatuses = []model.MapfixStatus{
|
||||
model.MapfixStatusUploading,
|
||||
model.MapfixStatusValidated,
|
||||
model.MapfixStatusValidating,
|
||||
model.MapfixStatusAcceptedUnvalidated,
|
||||
model.MapfixStatusChangesRequested,
|
||||
model.MapfixStatusSubmitted,
|
||||
model.MapfixStatusUnderConstruction,
|
||||
}
|
||||
)
|
||||
|
||||
var(
|
||||
ErrActiveMapfixSameAssetID = errors.New("There is an active mapfix with the same AssetID")
|
||||
ErrNotAssetOwner = errors.New("You can only submit an asset you own")
|
||||
)
|
||||
|
||||
// UpdateMapfixValidatedModel implements patchMapfixModel operation.
|
||||
//
|
||||
// Update model following role restrictions.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/validated-model
|
||||
func (svc *Service) UpdateMapfixValidatedModel(ctx context.Context, params internal.UpdateMapfixValidatedModelParams) error {
|
||||
ValidatedModelID := uint64(params.ValidatedModelID)
|
||||
ValidatedModelVersion := uint64(params.ValidatedModelVersion)
|
||||
|
||||
// check if Status is ChangesRequested|Submitted|UnderConstruction
|
||||
pmap := datastore.Optional()
|
||||
pmap.Add("validated_asset_id", ValidatedModelID)
|
||||
pmap.Add("validated_asset_version", ValidatedModelVersion)
|
||||
// DO NOT reset completed when validated model is updated
|
||||
// pmap.Add("completed", false)
|
||||
err := svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, pmap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataChangeValidatedModel{
|
||||
ValidatedModelID: ValidatedModelID,
|
||||
ValidatedModelVersion: ValidatedModelVersion,
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: ValidtorUserID,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeChangeValidatedModel,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionMapfixValidate invokes actionMapfixValidate operation.
|
||||
//
|
||||
// Role Validator changes status from Submitting -> Submitted.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-submitted
|
||||
func (svc *Service) ActionMapfixSubmitted(ctx context.Context, params internal.ActionMapfixSubmittedParams) error {
|
||||
// transaction
|
||||
target_status := model.MapfixStatusSubmitted
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err := svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusSubmitting}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: ValidtorUserID,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionMapfixValidate invokes actionMapfixValidate operation.
|
||||
//
|
||||
// Role Validator changes status from Validating -> Validated.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-validated
|
||||
func (svc *Service) ActionMapfixValidated(ctx context.Context, params internal.ActionMapfixValidatedParams) error {
|
||||
// transaction
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.MapfixStatusValidated)
|
||||
return svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, smap)
|
||||
}
|
||||
|
||||
// ActionMapfixAccepted implements actionMapfixAccepted operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-failed
|
||||
func (svc *Service) ActionMapfixAccepted(ctx context.Context, params internal.ActionMapfixAcceptedParams) error {
|
||||
// transaction
|
||||
target_status := model.MapfixStatusAcceptedUnvalidated
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
smap.Add("status_message", params.StatusMessage)
|
||||
err := svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: ValidtorUserID,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionMapfixUploaded implements actionMapfixUploaded operation.
|
||||
//
|
||||
// (Internal endpoint) Role Validator changes status from Uploading -> Uploaded.
|
||||
//
|
||||
// POST /mapfixes/{MapfixID}/status/validator-uploaded
|
||||
func (svc *Service) ActionMapfixUploaded(ctx context.Context, params internal.ActionMapfixUploadedParams) error {
|
||||
// transaction
|
||||
target_status := model.MapfixStatusUploaded
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err := svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusUploading}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: ValidtorUserID,
|
||||
ResourceType: model.ResourceMapfix,
|
||||
ResourceID: params.MapfixID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// POST /mapfixes
|
||||
func (svc *Service) CreateMapfix(ctx context.Context, request *internal.MapfixCreate) (*internal.MapfixID, error) {
|
||||
// sanitization
|
||||
if request.GameID<0||
|
||||
request.AssetOwner<0||
|
||||
request.AssetID<0||
|
||||
request.AssetVersion<0||
|
||||
request.TargetAssetID<0{
|
||||
return nil, ErrNegativeID
|
||||
}
|
||||
var GameID=uint32(request.GameID);
|
||||
var Submitter=uint64(request.AssetOwner);
|
||||
var AssetID=uint64(request.AssetID);
|
||||
var AssetVersion=uint64(request.AssetVersion);
|
||||
var TargetAssetID=uint64(request.TargetAssetID);
|
||||
|
||||
// Check if an active mapfix with the same asset id exists
|
||||
{
|
||||
filter := datastore.Optional()
|
||||
filter.Add("asset_id", request.AssetID)
|
||||
filter.Add("asset_version", request.AssetVersion)
|
||||
filter.Add("status_id", ActiveMapfixStatuses)
|
||||
active_mapfixes, err := svc.DB.Mapfixes().List(ctx, filter, model.Page{
|
||||
Number: 1,
|
||||
Size: 1,
|
||||
},datastore.ListSortDisabled)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(active_mapfixes) != 0{
|
||||
return nil, ErrActiveMapfixSameAssetID
|
||||
}
|
||||
}
|
||||
|
||||
operation, err := svc.DB.Operations().Get(ctx, request.OperationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check if user owns asset
|
||||
// TODO: allow bypass by admin
|
||||
if operation.Owner != Submitter {
|
||||
return nil, ErrNotAssetOwner
|
||||
}
|
||||
|
||||
mapfix, err := svc.DB.Mapfixes().Create(ctx, model.Mapfix{
|
||||
ID: 0,
|
||||
DisplayName: request.DisplayName,
|
||||
Creator: request.Creator,
|
||||
GameID: GameID,
|
||||
Submitter: Submitter,
|
||||
AssetID: AssetID,
|
||||
AssetVersion: AssetVersion,
|
||||
Completed: false,
|
||||
TargetAssetID: TargetAssetID,
|
||||
StatusID: model.MapfixStatusUnderConstruction,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// mark the operation as completed and provide the path
|
||||
pmap := datastore.Optional()
|
||||
pmap.Add("status_id", model.OperationStatusCompleted)
|
||||
pmap.Add("path", fmt.Sprintf("/mapfixes/%d", mapfix.ID))
|
||||
err = svc.DB.Operations().Update(ctx, request.OperationID, pmap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &internal.MapfixID{
|
||||
MapfixID: mapfix.ID,
|
||||
}, nil
|
||||
}
|
||||
21
pkg/service_internal/operations.go
Normal file
21
pkg/service_internal/operations.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package service_internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
// ActionOperationFailed implements actionOperationFailed operation.
|
||||
//
|
||||
// Fail the specified OperationID with a StatusMessage.
|
||||
//
|
||||
// POST /operations/{OperationID}/status/operation-failed
|
||||
func (svc *Service) ActionOperationFailed(ctx context.Context, params internal.ActionOperationFailedParams) (error) {
|
||||
pmap := datastore.Optional()
|
||||
pmap.Add("status_id", model.OperationStatusFailed)
|
||||
pmap.Add("status_message", params.StatusMessage)
|
||||
return svc.DB.Operations().Update(ctx, params.OperationID, pmap)
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
api "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
// Create a new script policy.
|
||||
//
|
||||
// POST /script-policy
|
||||
func (svc *Service) CreateScriptPolicy(ctx context.Context, req *api.ScriptPolicyCreate) (*api.ID, error) {
|
||||
func (svc *Service) CreateScriptPolicy(ctx context.Context, req *api.ScriptPolicyCreate) (*api.ScriptPolicyID, error) {
|
||||
from_script, err := svc.DB.Scripts().Get(ctx, req.FromScriptID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -31,8 +31,8 @@ func (svc *Service) CreateScriptPolicy(ctx context.Context, req *api.ScriptPolic
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.ID{
|
||||
ID: script.ID,
|
||||
return &api.ScriptPolicyID{
|
||||
ScriptPolicyID: script.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -49,13 +49,13 @@ func (svc *Service) ListScriptPolicy(ctx context.Context, params api.ListScriptP
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filter.AddNotNil("from_script_hash", int64(hash)) // No type safety!
|
||||
filter.Add("from_script_hash", int64(hash)) // No type safety!
|
||||
}
|
||||
if params.ToScriptID.IsSet(){
|
||||
filter.AddNotNil("to_script_id", params.ToScriptID.Value)
|
||||
filter.Add("to_script_id", params.ToScriptID.Value)
|
||||
}
|
||||
if params.Policy.IsSet(){
|
||||
filter.AddNotNil("policy", params.Policy.Value)
|
||||
filter.Add("policy", params.Policy.Value)
|
||||
}
|
||||
|
||||
items, err := svc.DB.ScriptPolicy().List(ctx, filter, model.Page{
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
api "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
// Create a new script.
|
||||
//
|
||||
// POST /scripts
|
||||
func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*api.ID, error) {
|
||||
func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*api.ScriptID, error) {
|
||||
script, err := svc.DB.Scripts().Create(ctx, model.Script{
|
||||
ID: 0,
|
||||
Name: req.Name,
|
||||
@@ -26,8 +26,8 @@ func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*a
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.ID{
|
||||
ID: script.ID,
|
||||
return &api.ScriptID{
|
||||
ScriptID: script.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -44,16 +44,19 @@ func (svc *Service) ListScripts(ctx context.Context, params api.ListScriptsParam
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filter.AddNotNil("hash", int64(hash)) // No type safety!
|
||||
filter.Add("hash", int64(hash)) // No type safety!
|
||||
}
|
||||
if params.Name.IsSet(){
|
||||
filter.AddNotNil("name", params.Name.Value)
|
||||
filter.Add("name", params.Name.Value)
|
||||
}
|
||||
if params.Source.IsSet(){
|
||||
filter.AddNotNil("source", params.Source.Value)
|
||||
filter.Add("source", params.Source.Value)
|
||||
}
|
||||
if params.SubmissionID.IsSet(){
|
||||
filter.AddNotNil("submission_id", params.SubmissionID.Value)
|
||||
if params.ResourceType.IsSet(){
|
||||
filter.Add("resource_type", params.ResourceType.Value)
|
||||
}
|
||||
if params.ResourceID.IsSet(){
|
||||
filter.Add("resource_id", params.ResourceID.Value)
|
||||
}
|
||||
|
||||
items, err := svc.DB.Scripts().List(ctx, filter, model.Page{
|
||||
|
||||
@@ -3,12 +3,21 @@ package service_internal
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"math"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"github.com/nats-io/nats.go"
|
||||
)
|
||||
|
||||
const (
|
||||
ValidtorUserID uint64 = uint64(math.MaxInt64)
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNegativeID = errors.New("A negative ID was provided")
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
DB datastore.Datastore
|
||||
Nats nats.JetStreamContext
|
||||
|
||||
@@ -2,25 +2,114 @@ package service_internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
var(
|
||||
// prevent two mapfixes with same asset id
|
||||
ActiveSubmissionStatuses = []model.SubmissionStatus{
|
||||
model.SubmissionStatusUploading,
|
||||
model.SubmissionStatusValidated,
|
||||
model.SubmissionStatusValidating,
|
||||
model.SubmissionStatusAcceptedUnvalidated,
|
||||
model.SubmissionStatusChangesRequested,
|
||||
model.SubmissionStatusSubmitted,
|
||||
model.SubmissionStatusUnderConstruction,
|
||||
}
|
||||
)
|
||||
|
||||
var(
|
||||
ErrActiveSubmissionSameAssetID = errors.New("There is an active submission with the same AssetID")
|
||||
)
|
||||
|
||||
// UpdateSubmissionValidatedModel implements patchSubmissionModel operation.
|
||||
//
|
||||
// Update model following role restrictions.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/validated-model
|
||||
func (svc *Service) UpdateSubmissionValidatedModel(ctx context.Context, params internal.UpdateSubmissionValidatedModelParams) error {
|
||||
ValidatedModelID := uint64(params.ValidatedModelID)
|
||||
ValidatedModelVersion := uint64(params.ValidatedModelVersion)
|
||||
|
||||
// check if Status is ChangesRequested|Submitted|UnderConstruction
|
||||
pmap := datastore.Optional()
|
||||
pmap.AddNotNil("validated_asset_id", params.ValidatedModelID)
|
||||
pmap.AddNotNil("validated_asset_version", params.ValidatedModelVersion)
|
||||
pmap.Add("validated_asset_id", ValidatedModelID)
|
||||
pmap.Add("validated_asset_version", ValidatedModelVersion)
|
||||
// DO NOT reset completed when validated model is updated
|
||||
// pmap.Add("completed", false)
|
||||
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, pmap)
|
||||
err := svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, pmap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataChangeValidatedModel{
|
||||
ValidatedModelID: ValidatedModelID,
|
||||
ValidatedModelVersion: ValidatedModelVersion,
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: ValidtorUserID,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeChangeValidatedModel,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionSubmissionValidate invokes actionSubmissionValidate operation.
|
||||
//
|
||||
// Role Validator changes status from Submitting -> Submitted.
|
||||
//
|
||||
// POST /submissions/{SubmissionID}/status/validator-submitted
|
||||
func (svc *Service) ActionSubmissionSubmitted(ctx context.Context, params internal.ActionSubmissionSubmittedParams) error {
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusSubmitted
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err := svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitting}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: ValidtorUserID,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionSubmissionValidate invokes actionSubmissionValidate operation.
|
||||
@@ -30,9 +119,36 @@ func (svc *Service) UpdateSubmissionValidatedModel(ctx context.Context, params i
|
||||
// POST /submissions/{SubmissionID}/status/validator-validated
|
||||
func (svc *Service) ActionSubmissionValidated(ctx context.Context, params internal.ActionSubmissionValidatedParams) error {
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusValidated
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.SubmissionStatusValidated)
|
||||
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, smap)
|
||||
smap.Add("status_id", target_status)
|
||||
err := svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: ValidtorUserID,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionSubmissionAccepted implements actionSubmissionAccepted operation.
|
||||
@@ -42,10 +158,37 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params intern
|
||||
// POST /submissions/{SubmissionID}/status/validator-failed
|
||||
func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params internal.ActionSubmissionAcceptedParams) error {
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusAcceptedUnvalidated
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.SubmissionStatusAccepted)
|
||||
smap.Add("status_id", target_status)
|
||||
smap.Add("status_message", params.StatusMessage)
|
||||
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, smap)
|
||||
err := svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: ValidtorUserID,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActionSubmissionUploaded implements actionSubmissionUploaded operation.
|
||||
@@ -55,8 +198,107 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params interna
|
||||
// POST /submissions/{SubmissionID}/status/validator-uploaded
|
||||
func (svc *Service) ActionSubmissionUploaded(ctx context.Context, params internal.ActionSubmissionUploadedParams) error {
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusUploaded
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.SubmissionStatusUploaded)
|
||||
smap.Add("status_id", target_status)
|
||||
smap.Add("uploaded_asset_id", params.UploadedAssetID)
|
||||
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusUploading}, smap)
|
||||
err := svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusUploading}, smap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event_data := model.AuditEventDataAction{
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: ValidtorUserID,
|
||||
ResourceType: model.ResourceSubmission,
|
||||
ResourceID: params.SubmissionID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// POST /submissions
|
||||
func (svc *Service) CreateSubmission(ctx context.Context, request *internal.SubmissionCreate) (*internal.SubmissionID, error) {
|
||||
// sanitization
|
||||
if request.GameID<0||
|
||||
request.AssetOwner<0||
|
||||
request.AssetID<0||
|
||||
request.AssetVersion<0{
|
||||
return nil, ErrNegativeID
|
||||
}
|
||||
var GameID=uint32(request.GameID);
|
||||
var Submitter=uint64(request.AssetOwner);
|
||||
var AssetID=uint64(request.AssetID);
|
||||
var AssetVersion=uint64(request.AssetVersion);
|
||||
|
||||
// Check if an active submission with the same asset id exists
|
||||
{
|
||||
filter := datastore.Optional()
|
||||
filter.Add("asset_id", request.AssetID)
|
||||
filter.Add("asset_version", request.AssetVersion)
|
||||
filter.Add("status_id", ActiveSubmissionStatuses)
|
||||
active_submissions, err := svc.DB.Submissions().List(ctx, filter, model.Page{
|
||||
Number: 1,
|
||||
Size: 1,
|
||||
},datastore.ListSortDisabled)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(active_submissions) != 0{
|
||||
return nil, ErrActiveSubmissionSameAssetID
|
||||
}
|
||||
}
|
||||
|
||||
operation, err := svc.DB.Operations().Get(ctx, request.OperationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check if user owns asset
|
||||
// TODO: allow bypass by admin
|
||||
if operation.Owner != Submitter {
|
||||
return nil, ErrNotAssetOwner
|
||||
}
|
||||
|
||||
submission, err := svc.DB.Submissions().Create(ctx, model.Submission{
|
||||
ID: 0,
|
||||
DisplayName: request.DisplayName,
|
||||
Creator: request.Creator,
|
||||
GameID: GameID,
|
||||
Submitter: Submitter,
|
||||
AssetID: AssetID,
|
||||
AssetVersion: AssetVersion,
|
||||
Completed: false,
|
||||
StatusID: model.SubmissionStatusUnderConstruction,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// mark the operation as completed and provide the path
|
||||
pmap := datastore.Optional()
|
||||
pmap.Add("status_id", model.OperationStatusCompleted)
|
||||
pmap.Add("path", fmt.Sprintf("/submissions/%d", submission.ID))
|
||||
err = svc.DB.Operations().Update(ctx, request.OperationID, pmap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &internal.SubmissionID{
|
||||
SubmissionID: submission.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ edition = "2021"
|
||||
submissions-api = { path = "api", features = ["internal"], default-features = false, registry = "strafesnet" }
|
||||
async-nats = "0.40.0"
|
||||
futures = "0.3.31"
|
||||
rbx_asset = { version = "0.2.5", registry = "strafesnet" }
|
||||
rbx_asset = { version = "0.4.3", registry = "strafesnet" }
|
||||
rbx_binary = { version = "0.7.4", registry = "strafesnet"}
|
||||
rbx_dom_weak = { version = "2.9.0", registry = "strafesnet"}
|
||||
rbx_reflection_database = { version = "0.2.12", registry = "strafesnet"}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Using the `rust-musl-builder` as base image, instead of
|
||||
# the official Rust toolchain
|
||||
FROM docker.io/clux/muslrust:stable AS chef
|
||||
FROM registry.itzana.me/docker-proxy/clux/muslrust:1.86.0-stable AS chef
|
||||
USER root
|
||||
RUN cargo install cargo-chef
|
||||
WORKDIR /app
|
||||
@@ -17,7 +17,7 @@ RUN cargo chef cook --release --target x86_64-unknown-linux-musl --recipe-path r
|
||||
COPY . .
|
||||
RUN cargo build --release --target x86_64-unknown-linux-musl --bin maps-validation
|
||||
|
||||
FROM docker.io/alpine:latest AS runtime
|
||||
FROM registry.itzana.me/docker-proxy/alpine:3.21 AS runtime
|
||||
RUN addgroup -S myuser && adduser -S myuser -G myuser
|
||||
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/maps-validation /usr/local/bin/
|
||||
USER myuser
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "submissions-api"
|
||||
version = "0.6.1"
|
||||
version = "0.7.0"
|
||||
edition = "2021"
|
||||
publish = ["strafesnet"]
|
||||
repository = "https://git.itzana.me/StrafesNET/maps-service"
|
||||
|
||||
@@ -14,7 +14,7 @@ impl Context{
|
||||
response_ok(
|
||||
self.0.get(url).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?
|
||||
.json().await.map_err(Error::Reqwest)
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
pub async fn get_scripts<'a>(&self,config:GetScriptsRequest<'a>)->Result<Vec<ScriptResponse>,Error>{
|
||||
let url_raw=format!("{}/scripts",self.0.base_url);
|
||||
@@ -33,15 +33,18 @@ impl Context{
|
||||
if let Some(source)=config.Source{
|
||||
query_pairs.append_pair("Source",source);
|
||||
}
|
||||
if let Some(submission_id)=config.SubmissionID{
|
||||
query_pairs.append_pair("SubmissionID",submission_id.to_string().as_str());
|
||||
if let Some(resource_type)=config.ResourceType{
|
||||
query_pairs.append_pair("ResourceType",(resource_type as i32).to_string().as_str());
|
||||
}
|
||||
if let Some(resource_id)=config.ResourceID{
|
||||
query_pairs.append_pair("ResourceID",resource_id.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::Reqwest)
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
pub async fn get_script_from_hash<'a>(&self,config:HashRequest<'a>)->Result<Option<ScriptResponse>,SingleItemError>{
|
||||
let scripts=self.get_scripts(GetScriptsRequest{
|
||||
@@ -50,7 +53,8 @@ impl Context{
|
||||
Hash:Some(config.hash),
|
||||
Name:None,
|
||||
Source:None,
|
||||
SubmissionID:None,
|
||||
ResourceType:None,
|
||||
ResourceID:None,
|
||||
}).await.map_err(SingleItemError::Other)?;
|
||||
if 1<scripts.len(){
|
||||
return Err(SingleItemError::DuplicateItems);
|
||||
@@ -66,7 +70,7 @@ impl Context{
|
||||
response_ok(
|
||||
self.0.post(url,body).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?
|
||||
.json().await.map_err(Error::Reqwest)
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
pub async fn get_script_policies<'a>(&self,config:GetScriptPoliciesRequest<'a>)->Result<Vec<ScriptPolicyResponse>,Error>{
|
||||
let url_raw=format!("{}/script-policy",self.0.base_url);
|
||||
@@ -90,7 +94,7 @@ impl Context{
|
||||
response_ok(
|
||||
self.0.get(url).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?
|
||||
.json().await.map_err(Error::Reqwest)
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
pub async fn get_script_policy_from_hash<'a>(&self,config:HashRequest<'a>)->Result<Option<ScriptPolicyResponse>,SingleItemError>{
|
||||
let policies=self.get_script_policies(GetScriptPoliciesRequest{
|
||||
@@ -114,7 +118,7 @@ impl Context{
|
||||
response_ok(
|
||||
self.0.post(url,body).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?
|
||||
.json().await.map_err(Error::Reqwest)
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
pub async fn update_script_policy(&self,config:UpdateScriptPolicyRequest)->Result<(),Error>{
|
||||
let url_raw=format!("{}/script-policy/{}",self.0.base_url,config.ID.0);
|
||||
|
||||
@@ -3,12 +3,27 @@ use crate::types::*;
|
||||
#[derive(Clone)]
|
||||
pub struct Context(crate::context::Context);
|
||||
|
||||
// conditionally include specified query pairs
|
||||
macro_rules! query_pairs{
|
||||
($url:expr,)=>{
|
||||
$url
|
||||
};
|
||||
($url:expr,$(($param:expr,$value:expr))+)=>{
|
||||
{
|
||||
let mut url=$url;
|
||||
url.query_pairs_mut()
|
||||
$(.append_pair($param,$value))*;
|
||||
url
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// there are lots of action endpoints and they all follow the same pattern
|
||||
macro_rules! action{
|
||||
($fname:ident,$action:expr)=>{
|
||||
pub async fn $fname(&self,config:SubmissionID)->Result<(),Error>{
|
||||
let url_raw=format!(concat!("{}/submissions/{}/status/",$action),self.0.base_url,config.0);
|
||||
let url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||
($system:expr,$fname:ident,$config:ident,$config_type:ident,$action:expr,$config_submission_id:expr,$(($param:expr,$value:expr))*)=>{
|
||||
pub async fn $fname(&self,$config:$config_type)->Result<(),Error>{
|
||||
let url_raw=format!(concat!("{}/",$system,"/{}/",$action),self.0.base_url,$config_submission_id);
|
||||
let url=query_pairs!(reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?,$(($param,$value))*);
|
||||
|
||||
response_ok(
|
||||
self.0.post_empty_body(url).await.map_err(Error::Reqwest)?
|
||||
@@ -29,7 +44,7 @@ impl Context{
|
||||
response_ok(
|
||||
self.0.get(url).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?
|
||||
.json().await.map_err(Error::Reqwest)
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
pub async fn get_scripts<'a>(&self,config:GetScriptsRequest<'a>)->Result<Vec<ScriptResponse>,Error>{
|
||||
let url_raw=format!("{}/scripts",self.0.base_url);
|
||||
@@ -48,15 +63,18 @@ impl Context{
|
||||
if let Some(source)=config.Source{
|
||||
query_pairs.append_pair("Source",source);
|
||||
}
|
||||
if let Some(submission_id)=config.SubmissionID{
|
||||
query_pairs.append_pair("SubmissionID",submission_id.to_string().as_str());
|
||||
if let Some(resource_type)=config.ResourceType{
|
||||
query_pairs.append_pair("ResourceType",(resource_type as i32).to_string().as_str());
|
||||
}
|
||||
if let Some(resource_id)=config.ResourceID{
|
||||
query_pairs.append_pair("ResourceID",resource_id.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::Reqwest)
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
pub async fn get_script_from_hash<'a>(&self,config:HashRequest<'a>)->Result<Option<ScriptResponse>,SingleItemError>{
|
||||
let scripts=self.get_scripts(GetScriptsRequest{
|
||||
@@ -65,7 +83,8 @@ impl Context{
|
||||
Hash:Some(config.hash),
|
||||
Name:None,
|
||||
Source:None,
|
||||
SubmissionID:None,
|
||||
ResourceType:None,
|
||||
ResourceID:None,
|
||||
}).await.map_err(SingleItemError::Other)?;
|
||||
if 1<scripts.len(){
|
||||
return Err(SingleItemError::DuplicateItems);
|
||||
@@ -81,7 +100,7 @@ impl Context{
|
||||
response_ok(
|
||||
self.0.post(url,body).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?
|
||||
.json().await.map_err(Error::Reqwest)
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
pub async fn get_script_policies<'a>(&self,config:GetScriptPoliciesRequest<'a>)->Result<Vec<ScriptPolicyResponse>,Error>{
|
||||
let url_raw=format!("{}/script-policy",self.0.base_url);
|
||||
@@ -105,7 +124,7 @@ impl Context{
|
||||
response_ok(
|
||||
self.0.get(url).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?
|
||||
.json().await.map_err(Error::Reqwest)
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
pub async fn get_script_policy_from_hash<'a>(&self,config:HashRequest<'a>)->Result<Option<ScriptPolicyResponse>,SingleItemError>{
|
||||
let policies=self.get_script_policies(GetScriptPoliciesRequest{
|
||||
@@ -129,52 +148,54 @@ impl Context{
|
||||
response_ok(
|
||||
self.0.post(url,body).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?
|
||||
.json().await.map_err(Error::Reqwest)
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
pub async fn update_submission_validated_model(&self,config:UpdateSubmissionModelRequest)->Result<(),Error>{
|
||||
let url_raw=format!("{}/submissions/{}/validated-model",self.0.base_url,config.SubmissionID);
|
||||
let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||
pub async fn create_submission<'a>(&self,config:CreateSubmissionRequest<'a>)->Result<SubmissionIDResponse,Error>{
|
||||
let url_raw=format!("{}/submissions",self.0.base_url);
|
||||
let url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||
|
||||
{
|
||||
url.query_pairs_mut()
|
||||
.append_pair("ValidatedModelID",config.ModelID.to_string().as_str())
|
||||
.append_pair("ValidatedModelVersion",config.ModelVersion.to_string().as_str());
|
||||
}
|
||||
let body=serde_json::to_string(&config).map_err(Error::JSON)?;
|
||||
|
||||
response_ok(
|
||||
self.0.post_empty_body(url).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?;
|
||||
|
||||
Ok(())
|
||||
self.0.post(url,body).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
pub async fn action_submission_uploaded(&self,config:ActionSubmissionUploadedRequest)->Result<(),Error>{
|
||||
let url_raw=format!("{}/submissions/{}/status/validator-uploaded",self.0.base_url,config.SubmissionID);
|
||||
let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||
// simple submission endpoints
|
||||
action!("submissions",action_submission_validated,config,SubmissionID,"status/validator-validated",config.0,);
|
||||
action!("submissions",update_submission_validated_model,config,UpdateSubmissionModelRequest,"validated-model",config.SubmissionID,
|
||||
("ValidatedModelID",config.ModelID.to_string().as_str())
|
||||
("ValidatedModelVersion",config.ModelVersion.to_string().as_str())
|
||||
);
|
||||
action!("submissions",action_submission_uploaded,config,ActionSubmissionUploadedRequest,"status/validator-uploaded",config.SubmissionID,
|
||||
("UploadedAssetID",config.UploadedAssetID.to_string().as_str())
|
||||
);
|
||||
action!("submissions",action_submission_accepted,config,ActionSubmissionAcceptedRequest,"status/validator-failed",config.SubmissionID,
|
||||
("StatusMessage",config.StatusMessage.as_str())
|
||||
);
|
||||
pub async fn create_mapfix<'a>(&self,config:CreateMapfixRequest<'a>)->Result<MapfixIDResponse,Error>{
|
||||
let url_raw=format!("{}/mapfixes",self.0.base_url);
|
||||
let url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||
|
||||
{
|
||||
url.query_pairs_mut()
|
||||
.append_pair("UploadedAssetID",config.UploadedAssetID.to_string().as_str());
|
||||
}
|
||||
response_ok(
|
||||
self.0.post_empty_body(url).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub async fn action_submission_accepted(&self,config:ActionSubmissionAcceptedRequest)->Result<(),Error>{
|
||||
let url_raw=format!("{}/submissions/{}/status/validator-failed",self.0.base_url,config.SubmissionID);
|
||||
let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||
|
||||
{
|
||||
url.query_pairs_mut()
|
||||
.append_pair("StatusMessage",config.StatusMessage.as_str());
|
||||
}
|
||||
let body=serde_json::to_string(&config).map_err(Error::JSON)?;
|
||||
|
||||
response_ok(
|
||||
self.0.post_empty_body(url).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?;
|
||||
|
||||
Ok(())
|
||||
self.0.post(url,body).await.map_err(Error::Reqwest)?
|
||||
).await.map_err(Error::Response)?
|
||||
.json().await.map_err(Error::ReqwestJson)
|
||||
}
|
||||
action!(action_submission_validated,"validator-validated");
|
||||
// simple mapfixes endpoints
|
||||
action!("mapfixes",action_mapfix_validated,config,MapfixID,"status/validator-validated",config.0,);
|
||||
action!("mapfixes",update_mapfix_validated_model,config,UpdateMapfixModelRequest,"validated-model",config.MapfixID,
|
||||
("ValidatedModelID",config.ModelID.to_string().as_str())
|
||||
("ValidatedModelVersion",config.ModelVersion.to_string().as_str())
|
||||
);
|
||||
action!("mapfixes",action_mapfix_uploaded,config,ActionMapfixUploadedRequest,"status/validator-uploaded",config.MapfixID,);
|
||||
action!("mapfixes",action_mapfix_accepted,config,ActionMapfixAcceptedRequest,"status/validator-failed",config.MapfixID,
|
||||
("StatusMessage",config.StatusMessage.as_str())
|
||||
);
|
||||
// simple operation endpoint
|
||||
action!("operations",action_operation_failed,config,ActionOperationFailedRequest,"status/operation-failed",config.OperationID,
|
||||
("StatusMessage",config.StatusMessage.as_str())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
pub enum Error{
|
||||
Parse(url::ParseError),
|
||||
Reqwest(reqwest::Error),
|
||||
ReqwestJson(reqwest::Error),
|
||||
Response(ResponseError),
|
||||
JSON(serde_json::Error),
|
||||
}
|
||||
@@ -60,11 +61,55 @@ pub async fn response_ok(response:reqwest::Response)->Result<reqwest::Response,R
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug,serde::Serialize)]
|
||||
pub struct CreateMapfixRequest<'a>{
|
||||
pub OperationID:i32,
|
||||
pub AssetOwner:i64,
|
||||
pub DisplayName:&'a str,
|
||||
pub Creator:&'a str,
|
||||
pub GameID:i32,
|
||||
pub AssetID:u64,
|
||||
pub AssetVersion:u64,
|
||||
pub TargetAssetID:u64,
|
||||
}
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug,serde::Deserialize)]
|
||||
pub struct MapfixIDResponse{
|
||||
pub MapfixID:MapfixID,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug,serde::Serialize)]
|
||||
pub struct CreateSubmissionRequest<'a>{
|
||||
pub OperationID:i32,
|
||||
pub AssetOwner:i64,
|
||||
pub DisplayName:&'a str,
|
||||
pub Creator:&'a str,
|
||||
pub GameID:i32,
|
||||
pub AssetID:u64,
|
||||
pub AssetVersion:u64,
|
||||
}
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug,serde::Deserialize)]
|
||||
pub struct SubmissionIDResponse{
|
||||
pub SubmissionID:SubmissionID,
|
||||
}
|
||||
|
||||
#[derive(Clone,Copy,Debug,PartialEq,Eq,serde::Serialize,serde::Deserialize)]
|
||||
pub struct ScriptID(pub(crate)i64);
|
||||
#[derive(Clone,Copy,Debug,serde::Serialize,serde::Deserialize)]
|
||||
pub struct ScriptPolicyID(pub(crate)i64);
|
||||
|
||||
#[derive(Clone,Copy,Debug,PartialEq,Eq,serde_repr::Serialize_repr,serde_repr::Deserialize_repr)]
|
||||
#[repr(i32)]
|
||||
pub enum ResourceType{
|
||||
Unknown=0,
|
||||
Mapfix=1,
|
||||
Submission=2,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
pub struct GetScriptRequest{
|
||||
pub ScriptID:ScriptID,
|
||||
@@ -81,7 +126,9 @@ pub struct GetScriptsRequest<'a>{
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub Source:Option<&'a str>,
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub SubmissionID:Option<i64>,
|
||||
pub ResourceType:Option<ResourceType>,
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub ResourceID:Option<i64>,
|
||||
}
|
||||
#[derive(Clone,Copy,Debug)]
|
||||
pub struct HashRequest<'a>{
|
||||
@@ -94,20 +141,22 @@ pub struct ScriptResponse{
|
||||
pub Name:String,
|
||||
pub Hash:String,
|
||||
pub Source:String,
|
||||
pub SubmissionID:i64,
|
||||
pub ResourceType:ResourceType,
|
||||
pub ResourceID:i64,
|
||||
}
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug,serde::Serialize)]
|
||||
pub struct CreateScriptRequest<'a>{
|
||||
pub Name:&'a str,
|
||||
pub Source:&'a str,
|
||||
pub ResourceType:ResourceType,
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub SubmissionID:Option<i64>,
|
||||
pub ResourceID:Option<i64>,
|
||||
}
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug,serde::Deserialize)]
|
||||
pub struct ScriptIDResponse{
|
||||
pub ID:ScriptID,
|
||||
pub ScriptID:ScriptID,
|
||||
}
|
||||
|
||||
#[derive(Clone,Copy,Debug,PartialEq,Eq,serde_repr::Serialize_repr,serde_repr::Deserialize_repr)]
|
||||
@@ -150,7 +199,7 @@ pub struct CreateScriptPolicyRequest{
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug,serde::Deserialize)]
|
||||
pub struct ScriptPolicyIDResponse{
|
||||
pub ID:ScriptPolicyID,
|
||||
pub ScriptPolicyID:ScriptPolicyID,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
@@ -187,5 +236,36 @@ pub struct ActionSubmissionAcceptedRequest{
|
||||
pub StatusMessage:String,
|
||||
}
|
||||
|
||||
#[derive(Clone,Copy,Debug)]
|
||||
#[derive(Clone,Copy,Debug,serde::Deserialize)]
|
||||
pub struct SubmissionID(pub i64);
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct UpdateMapfixModelRequest{
|
||||
pub MapfixID:i64,
|
||||
pub ModelID:u64,
|
||||
pub ModelVersion:u64,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct ActionMapfixUploadedRequest{
|
||||
pub MapfixID:i64,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct ActionMapfixAcceptedRequest{
|
||||
pub MapfixID:i64,
|
||||
pub StatusMessage:String,
|
||||
}
|
||||
|
||||
#[derive(Clone,Copy,Debug,serde::Deserialize)]
|
||||
pub struct MapfixID(pub i64);
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct ActionOperationFailedRequest{
|
||||
pub OperationID:i32,
|
||||
pub StatusMessage:String,
|
||||
}
|
||||
|
||||
86
validation/src/create.rs
Normal file
86
validation/src/create.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
use crate::rbx_util::{get_mapinfo,read_dom,MapInfo,ReadDomError,GetMapInfoError,ParseGameIDError};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
CreatorTypeMustBeUser,
|
||||
ModelInfoDownload(rbx_asset::cloud::GetError),
|
||||
ModelLocationDownload(rbx_asset::cloud::GetError),
|
||||
NonFreeModel,
|
||||
ModelFileDownload(rbx_asset::cloud::GetError),
|
||||
ParseUserID(core::num::ParseIntError),
|
||||
ParseModelVersion(core::num::ParseIntError),
|
||||
ModelFileDecode(ReadDomError),
|
||||
GetMapInfo(GetMapInfoError),
|
||||
ParseGameID(ParseGameIDError),
|
||||
}
|
||||
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{}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
pub struct CreateRequest{
|
||||
pub ModelID:u64,
|
||||
}
|
||||
#[allow(nonstandard_style)]
|
||||
pub struct CreateResult{
|
||||
pub AssetOwner:i64,
|
||||
pub DisplayName:String,
|
||||
pub Creator:String,
|
||||
pub GameID:i32,
|
||||
pub AssetVersion:u64,
|
||||
}
|
||||
impl crate::message_handler::MessageHandler{
|
||||
pub async fn create_inner(&self,create_info:CreateRequest)->Result<CreateResult,Error>{
|
||||
// discover asset creator and latest version
|
||||
let info=self.cloud_context.get_asset_info(
|
||||
rbx_asset::cloud::GetAssetLatestRequest{asset_id:create_info.ModelID}
|
||||
).await.map_err(Error::ModelInfoDownload)?;
|
||||
|
||||
// reject models created by a group
|
||||
let rbx_asset::cloud::Creator::userId(user_id_string)=info.creationContext.creator else{
|
||||
return Err(Error::CreatorTypeMustBeUser);
|
||||
};
|
||||
|
||||
// parse user string and model version string
|
||||
let user_id:u64=user_id_string.parse().map_err(Error::ParseUserID)?;
|
||||
let asset_version=info.revisionId.parse().map_err(Error::ParseModelVersion)?;
|
||||
|
||||
// download the location of the map model
|
||||
let location=self.cloud_context.get_asset_version_location(rbx_asset::cloud::GetAssetVersionRequest{
|
||||
asset_id:create_info.ModelID,
|
||||
version:asset_version,
|
||||
}).await.map_err(Error::ModelLocationDownload)?;
|
||||
|
||||
// if the location does not exist, you are not allowed to donwload it
|
||||
let Some(location)=location.location else{
|
||||
return Err(Error::NonFreeModel);
|
||||
};
|
||||
|
||||
// download the map model
|
||||
let model_data=self.cloud_context.get_asset(&location).await.map_err(Error::ModelFileDownload)?;
|
||||
|
||||
// decode dom (slow!)
|
||||
let dom=read_dom(std::io::Cursor::new(model_data)).map_err(Error::ModelFileDecode)?;
|
||||
|
||||
// parse create fields out of asset
|
||||
let MapInfo{
|
||||
display_name,
|
||||
creator,
|
||||
game_id,
|
||||
}=get_mapinfo(&dom).map_err(Error::GetMapInfo)?;
|
||||
|
||||
let game_id=game_id.map_err(Error::ParseGameID)?;
|
||||
|
||||
Ok(CreateResult{
|
||||
AssetOwner:user_id as i64,
|
||||
DisplayName:display_name.unwrap_or_default().to_owned(),
|
||||
Creator:creator.unwrap_or_default().to_owned(),
|
||||
GameID:game_id as i32,
|
||||
AssetVersion:asset_version,
|
||||
})
|
||||
}
|
||||
}
|
||||
52
validation/src/create_mapfix.rs
Normal file
52
validation/src/create_mapfix.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use crate::nats_types::CreateMapfixRequest;
|
||||
use crate::create::CreateRequest;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
Create(crate::create::Error),
|
||||
ApiActionMapfixCreate(submissions_api::Error),
|
||||
}
|
||||
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{
|
||||
async fn create_mapfix_inner(&self,create_info:CreateMapfixRequest)->Result<(),Error>{
|
||||
// call deduplicated inner code
|
||||
let create_request=self.create_inner(CreateRequest{
|
||||
ModelID:create_info.ModelID,
|
||||
}).await.map_err(Error::Create)?;
|
||||
|
||||
// call create on api
|
||||
self.api.create_mapfix(submissions_api::types::CreateMapfixRequest{
|
||||
OperationID:create_info.OperationID,
|
||||
AssetOwner:create_request.AssetOwner,
|
||||
DisplayName:create_request.DisplayName.as_str(),
|
||||
Creator:create_request.Creator.as_str(),
|
||||
GameID:create_request.GameID,
|
||||
AssetID:create_info.ModelID,
|
||||
AssetVersion:create_request.AssetVersion,
|
||||
TargetAssetID:create_info.TargetAssetID,
|
||||
}).await.map_err(Error::ApiActionMapfixCreate)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub async fn create_mapfix(&self,create_info:CreateMapfixRequest)->Result<(),submissions_api::Error>{
|
||||
let operation_id=create_info.OperationID;
|
||||
|
||||
let create_result=self.create_mapfix_inner(create_info).await;
|
||||
|
||||
if let Err(e)=create_result{
|
||||
self.api.action_operation_failed(submissions_api::types::ActionOperationFailedRequest{
|
||||
OperationID:operation_id,
|
||||
StatusMessage:format!("{e}"),
|
||||
}).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
49
validation/src/create_submission.rs
Normal file
49
validation/src/create_submission.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use crate::nats_types::CreateSubmissionRequest;
|
||||
use crate::create::CreateRequest;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
Create(crate::create::Error),
|
||||
ApiActionSubmissionCreate(submissions_api::Error),
|
||||
}
|
||||
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{
|
||||
async fn create_submission_inner(&self,create_info:CreateSubmissionRequest)->Result<(),Error>{
|
||||
let create_request=self.create_inner(CreateRequest{
|
||||
ModelID:create_info.ModelID,
|
||||
}).await.map_err(Error::Create)?;
|
||||
// call create on api
|
||||
self.api.create_submission(submissions_api::types::CreateSubmissionRequest{
|
||||
OperationID:create_info.OperationID,
|
||||
AssetOwner:create_request.AssetOwner,
|
||||
DisplayName:create_request.DisplayName.as_str(),
|
||||
Creator:create_request.Creator.as_str(),
|
||||
GameID:create_request.GameID,
|
||||
AssetID:create_info.ModelID,
|
||||
AssetVersion:create_request.AssetVersion,
|
||||
}).await.map_err(Error::ApiActionSubmissionCreate)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub async fn create_submission(&self,create_info:CreateSubmissionRequest)->Result<(),submissions_api::Error>{
|
||||
let operation_id=create_info.OperationID;
|
||||
|
||||
let create_result=self.create_submission_inner(create_info).await;
|
||||
|
||||
if let Err(e)=create_result{
|
||||
self.api.action_operation_failed(submissions_api::types::ActionOperationFailedRequest{
|
||||
OperationID:operation_id,
|
||||
StatusMessage:format!("{e}"),
|
||||
}).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,17 @@
|
||||
use futures::StreamExt;
|
||||
|
||||
mod nats_types;
|
||||
mod validator;
|
||||
mod upload_submission;
|
||||
mod upload_mapfix;
|
||||
mod rbx_util;
|
||||
mod message_handler;
|
||||
mod nats_types;
|
||||
mod types;
|
||||
mod create;
|
||||
mod create_mapfix;
|
||||
mod create_submission;
|
||||
mod upload_mapfix;
|
||||
mod upload_submission;
|
||||
mod validator;
|
||||
mod validate_mapfix;
|
||||
mod validate_submission;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
@@ -13,6 +20,7 @@ pub enum StartupError{
|
||||
NatsConnect(async_nats::ConnectError),
|
||||
NatsGetStream(async_nats::jetstream::context::GetStreamError),
|
||||
NatsConsumer(async_nats::jetstream::stream::ConsumerError),
|
||||
NatsConsumerUpdate(async_nats::jetstream::stream::ConsumerUpdateError),
|
||||
NatsStream(async_nats::jetstream::consumer::StreamError),
|
||||
}
|
||||
impl std::fmt::Display for StartupError{
|
||||
@@ -34,9 +42,12 @@ async fn main()->Result<(),StartupError>{
|
||||
Err(e)=>Err(e).expect("ROBLOX_GROUP_ID env required"),
|
||||
};
|
||||
|
||||
// talk to roblox through STRAFESNET_CI2 account
|
||||
// create / upload models through STRAFESNET_CI2 account
|
||||
let cookie=std::env::var("RBXCOOKIE").expect("RBXCOOKIE env required");
|
||||
let cookie_context=rbx_asset::cookie::CookieContext::new(rbx_asset::cookie::Cookie::new(cookie));
|
||||
let cookie_context=rbx_asset::cookie::Context::new(rbx_asset::cookie::Cookie::new(cookie));
|
||||
// download models through cloud api
|
||||
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));
|
||||
|
||||
// maps-service api
|
||||
let api_host_internal=std::env::var("API_HOST_INTERNAL").expect("API_HOST_INTERNAL env required");
|
||||
@@ -45,20 +56,35 @@ async fn main()->Result<(),StartupError>{
|
||||
// nats
|
||||
let nats_host=std::env::var("NATS_HOST").expect("NATS_HOST env required");
|
||||
let nats_fut=async{
|
||||
const STREAM_NAME:&str="maptest";
|
||||
const DURABLE_NAME:&str="validation";
|
||||
const FILTER_SUBJECT:&str="maptest.>";
|
||||
|
||||
let nats_config=async_nats::jetstream::consumer::pull::Config{
|
||||
name:Some(DURABLE_NAME.to_owned()),
|
||||
durable_name:Some(DURABLE_NAME.to_owned()),
|
||||
filter_subject:FILTER_SUBJECT.to_owned(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let nasty=async_nats::connect(nats_host).await.map_err(StartupError::NatsConnect)?;
|
||||
|
||||
// use nats jetstream
|
||||
async_nats::jetstream::new(nasty)
|
||||
.get_stream("maptest").await.map_err(StartupError::NatsGetStream)?
|
||||
.get_or_create_consumer("validation",async_nats::jetstream::consumer::pull::Config{
|
||||
name:Some("validation".to_owned()),
|
||||
durable_name:Some("validation".to_owned()),
|
||||
filter_subject:"maptest.>".to_owned(),
|
||||
..Default::default()
|
||||
}).await.map_err(StartupError::NatsConsumer)?
|
||||
.messages().await.map_err(StartupError::NatsStream)
|
||||
let stream=async_nats::jetstream::new(nasty)
|
||||
.get_stream(STREAM_NAME).await.map_err(StartupError::NatsGetStream)?;
|
||||
|
||||
let consumer=stream.get_or_create_consumer(DURABLE_NAME,nats_config.clone()).await.map_err(StartupError::NatsConsumer)?;
|
||||
|
||||
// check if config matches expected config
|
||||
if consumer.cached_info().config.filter_subject!=FILTER_SUBJECT{
|
||||
stream.update_consumer(nats_config).await.map_err(StartupError::NatsConsumerUpdate)?;
|
||||
}
|
||||
|
||||
// only need messages
|
||||
consumer.messages().await.map_err(StartupError::NatsStream)
|
||||
};
|
||||
|
||||
let message_handler=message_handler::MessageHandler::new(cookie_context,group_id,api);
|
||||
let message_handler=message_handler::MessageHandler::new(cloud_context,cookie_context,group_id,api);
|
||||
|
||||
// Create a signal listener for SIGTERM
|
||||
let mut sig_term=tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()).expect("Failed to create SIGTERM signal listener");
|
||||
@@ -80,7 +106,7 @@ async fn main()->Result<(),StartupError>{
|
||||
Err(e)=>println!("[Validation] There was an error, oopsie! {e}"),
|
||||
}
|
||||
// explicitly call drop to make the move semantics and permit release more obvious
|
||||
core::mem::drop(permit);
|
||||
drop(permit);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,9 +5,12 @@ pub enum HandleMessageError{
|
||||
DoubleAck(async_nats::Error),
|
||||
Json(serde_json::Error),
|
||||
UnknownSubject(String),
|
||||
UploadNew(crate::upload_new::UploadError),
|
||||
UploadFix(crate::upload_fix::UploadError),
|
||||
Validation(crate::validator::ValidateError),
|
||||
CreateMapfix(submissions_api::Error),
|
||||
CreateSubmission(submissions_api::Error),
|
||||
UploadMapfix(crate::upload_mapfix::Error),
|
||||
UploadSubmission(crate::upload_submission::Error),
|
||||
ValidateMapfix(crate::validate_mapfix::Error),
|
||||
ValidateSubmission(crate::validate_submission::Error),
|
||||
}
|
||||
impl std::fmt::Display for HandleMessageError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
@@ -23,30 +26,36 @@ fn from_slice<'a,T:serde::de::Deserialize<'a>>(slice:&'a [u8])->Result<T,HandleM
|
||||
}
|
||||
|
||||
pub struct MessageHandler{
|
||||
upload_new:crate::upload_new::Uploader,
|
||||
upload_fix:crate::upload_fix::Uploader,
|
||||
validator:crate::validator::Validator,
|
||||
pub(crate) cloud_context:rbx_asset::cloud::Context,
|
||||
pub(crate) cookie_context:rbx_asset::cookie::Context,
|
||||
pub(crate) group_id:Option<u64>,
|
||||
pub(crate) api:submissions_api::internal::Context,
|
||||
}
|
||||
|
||||
impl MessageHandler{
|
||||
pub fn new(
|
||||
cookie_context:rbx_asset::cookie::CookieContext,
|
||||
cloud_context:rbx_asset::cloud::Context,
|
||||
cookie_context:rbx_asset::cookie::Context,
|
||||
group_id:Option<u64>,
|
||||
api:submissions_api::internal::Context,
|
||||
)->Self{
|
||||
Self{
|
||||
upload_new:crate::upload_new::Uploader::new(cookie_context.clone(),group_id,api.clone()),
|
||||
upload_fix:crate::upload_fix::Uploader::new(cookie_context.clone(),group_id,api.clone()),
|
||||
validator:crate::validator::Validator::new(cookie_context,api),
|
||||
cloud_context,
|
||||
cookie_context,
|
||||
group_id,
|
||||
api,
|
||||
}
|
||||
}
|
||||
pub async fn handle_message_result(&self,message_result:MessageResult)->Result<(),HandleMessageError>{
|
||||
let message=message_result.map_err(HandleMessageError::Messages)?;
|
||||
message.double_ack().await.map_err(HandleMessageError::DoubleAck)?;
|
||||
match message.subject.as_str(){
|
||||
"maptest.mapfixes.upload"=>self.upload_fix.upload(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadFix),
|
||||
"maptest.submissions.upload"=>self.upload_new.upload(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadNew),
|
||||
"maptest.submissions.validate"=>self.validator.validate(from_slice(&message.payload)?).await.map_err(HandleMessageError::Validation),
|
||||
"maptest.mapfixes.create"=>self.create_mapfix(from_slice(&message.payload)?).await.map_err(HandleMessageError::CreateMapfix),
|
||||
"maptest.submissions.create"=>self.create_submission(from_slice(&message.payload)?).await.map_err(HandleMessageError::CreateSubmission),
|
||||
"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),
|
||||
"maptest.submissions.validate"=>self.validate_submission(from_slice(&message.payload)?).await.map_err(HandleMessageError::ValidateSubmission),
|
||||
other=>Err(HandleMessageError::UnknownSubject(other.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,23 @@
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct ValidateRequest{
|
||||
pub struct CreateSubmissionRequest{
|
||||
// operation_id is passed back in the response message
|
||||
pub OperationID:i32,
|
||||
pub ModelID:u64,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct CreateMapfixRequest{
|
||||
pub OperationID:i32,
|
||||
pub ModelID:u64,
|
||||
pub TargetAssetID:u64,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct ValidateSubmissionRequest{
|
||||
// submission_id is passed back in the response message
|
||||
pub SubmissionID:i64,
|
||||
pub ModelID:u64,
|
||||
@@ -14,10 +30,20 @@ pub struct ValidateRequest{
|
||||
pub ValidatedModelID:Option<u64>,
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct ValidateMapfixRequest{
|
||||
// submission_id is passed back in the response message
|
||||
pub MapfixID:i64,
|
||||
pub ModelID:u64,
|
||||
pub ModelVersion:u64,
|
||||
pub ValidatedModelID:Option<u64>,
|
||||
}
|
||||
|
||||
// Create a new map
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct UploadNewRequest{
|
||||
pub struct UploadSubmissionRequest{
|
||||
pub SubmissionID:i64,
|
||||
pub ModelID:u64,
|
||||
pub ModelVersion:u64,
|
||||
@@ -26,8 +52,8 @@ pub struct UploadNewRequest{
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct UploadFixRequest{
|
||||
pub SubmissionID:i64,
|
||||
pub struct UploadMapfixRequest{
|
||||
pub MapfixID:i64,
|
||||
pub ModelID:u64,
|
||||
pub ModelVersion:u64,
|
||||
pub TargetAssetID:u64,
|
||||
|
||||
119
validation/src/rbx_util.rs
Normal file
119
validation/src/rbx_util.rs
Normal file
@@ -0,0 +1,119 @@
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum ReadDomError{
|
||||
Binary(rbx_binary::DecodeError),
|
||||
Xml(rbx_xml::DecodeError),
|
||||
Read(std::io::Error),
|
||||
Seek(std::io::Error),
|
||||
UnknownFormat([u8;8]),
|
||||
}
|
||||
impl std::fmt::Display for ReadDomError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for ReadDomError{}
|
||||
|
||||
pub fn read_dom<R:std::io::Read+std::io::Seek>(mut input:R)->Result<rbx_dom_weak::WeakDom,ReadDomError>{
|
||||
let mut first_8=[0u8;8];
|
||||
std::io::Read::read_exact(&mut input,&mut first_8).map_err(ReadDomError::Read)?;
|
||||
std::io::Seek::rewind(&mut input).map_err(ReadDomError::Seek)?;
|
||||
match &first_8[0..4]{
|
||||
b"<rob"=>{
|
||||
match &first_8[4..8]{
|
||||
b"lox!"=>rbx_binary::from_reader(input).map_err(ReadDomError::Binary),
|
||||
b"lox "=>rbx_xml::from_reader(input,rbx_xml::DecodeOptions::default()).map_err(ReadDomError::Xml),
|
||||
_=>Err(ReadDomError::UnknownFormat(first_8)),
|
||||
}
|
||||
},
|
||||
_=>Err(ReadDomError::UnknownFormat(first_8)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn class_is_a(class:&str,superclass:&str)->bool{
|
||||
if class==superclass{
|
||||
return true
|
||||
}
|
||||
let class_descriptor=rbx_reflection_database::get().classes.get(class);
|
||||
if let Some(descriptor)=&class_descriptor{
|
||||
if let Some(class_super)=&descriptor.superclass{
|
||||
return class_is_a(&class_super,superclass)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn find_first_child_class<'a>(dom:&'a rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance,name:&str,class:&str)->Option<&'a rbx_dom_weak::Instance>{
|
||||
for &referent in instance.children(){
|
||||
if let Some(c)=dom.get_by_ref(referent){
|
||||
if c.name==name&&class_is_a(c.class.as_str(),class) {
|
||||
return Some(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub enum GameID{
|
||||
Bhop=1,
|
||||
Surf=2,
|
||||
FlyTrials=5,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct ParseGameIDError;
|
||||
impl std::str::FromStr for GameID{
|
||||
type Err=ParseGameIDError;
|
||||
fn from_str(s:&str)->Result<Self,Self::Err>{
|
||||
if s.starts_with("bhop_"){
|
||||
return Ok(GameID::Bhop);
|
||||
}
|
||||
if s.starts_with("surf_"){
|
||||
return Ok(GameID::Surf);
|
||||
}
|
||||
if s.starts_with("flytrials_"){
|
||||
return Ok(GameID::FlyTrials);
|
||||
}
|
||||
return Err(ParseGameIDError);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MapInfo<'a>{
|
||||
pub display_name:Result<&'a str,StringValueError>,
|
||||
pub creator:Result<&'a str,StringValueError>,
|
||||
pub game_id:Result<GameID,ParseGameIDError>,
|
||||
}
|
||||
|
||||
pub enum StringValueError{
|
||||
ObjectNotFound,
|
||||
ValueNotSet,
|
||||
NonStringValue,
|
||||
}
|
||||
|
||||
fn string_value(instance:Option<&rbx_dom_weak::Instance>)->Result<&str,StringValueError>{
|
||||
let instance=instance.ok_or(StringValueError::ObjectNotFound)?;
|
||||
let value=instance.properties.get("Value").ok_or(StringValueError::ValueNotSet)?;
|
||||
match value{
|
||||
rbx_dom_weak::types::Variant::String(value)=>Ok(value),
|
||||
_=>Err(StringValueError::NonStringValue),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GetMapInfoError{
|
||||
ModelFileRootMustHaveOneChild,
|
||||
ModelFileChildRefIsNil,
|
||||
}
|
||||
|
||||
pub fn get_mapinfo(dom:&rbx_dom_weak::WeakDom)->Result<MapInfo,GetMapInfoError>{
|
||||
let &[map_ref]=dom.root().children()else{
|
||||
return Err(GetMapInfoError::ModelFileRootMustHaveOneChild);
|
||||
};
|
||||
let model_instance=dom.get_by_ref(map_ref).ok_or(GetMapInfoError::ModelFileChildRefIsNil)?;
|
||||
|
||||
Ok(MapInfo{
|
||||
display_name:string_value(find_first_child_class(dom,model_instance,"DisplayName","StringValue")),
|
||||
creator:string_value(find_first_child_class(dom,model_instance,"Creator","StringValue")),
|
||||
game_id:model_instance.name.parse(),
|
||||
})
|
||||
}
|
||||
4
validation/src/types.rs
Normal file
4
validation/src/types.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
pub enum ResourceID{
|
||||
Mapfix(i64),
|
||||
Submission(i64),
|
||||
}
|
||||
@@ -1,65 +1,54 @@
|
||||
use crate::nats_types::UploadFixRequest;
|
||||
use crate::nats_types::UploadMapfixRequest;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum UploadError{
|
||||
Get(rbx_asset::cookie::GetError),
|
||||
pub enum Error{
|
||||
GetLocation(rbx_asset::cloud::GetError),
|
||||
NonFreeModel,
|
||||
Get(rbx_asset::cloud::GetError),
|
||||
Json(serde_json::Error),
|
||||
Upload(rbx_asset::cookie::UploadError),
|
||||
ApiActionSubmissionUploaded(submissions_api::Error),
|
||||
Unimplemented,
|
||||
ApiActionMapfixUploaded(submissions_api::Error),
|
||||
}
|
||||
impl std::fmt::Display for UploadError{
|
||||
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 UploadError{}
|
||||
impl std::error::Error for Error{}
|
||||
|
||||
pub struct Uploader{
|
||||
roblox_cookie:rbx_asset::cookie::CookieContext,
|
||||
group_id:Option<u64>,
|
||||
api_internal:submissions_api::internal::Context,
|
||||
}
|
||||
impl Uploader{
|
||||
pub const fn new(
|
||||
roblox_cookie:rbx_asset::cookie::CookieContext,
|
||||
group_id:Option<u64>,
|
||||
api_internal:submissions_api::internal::Context,
|
||||
)->Self{
|
||||
Self{
|
||||
roblox_cookie,
|
||||
group_id,
|
||||
api_internal,
|
||||
}
|
||||
}
|
||||
pub async fn upload(&self,upload_info:UploadFixRequest)->Result<(),UploadError>{
|
||||
// download the map model version
|
||||
let model_data=self.roblox_cookie.get_asset(rbx_asset::cookie::GetAssetRequest{
|
||||
impl crate::message_handler::MessageHandler{
|
||||
pub async fn upload_mapfix(&self,upload_info:UploadMapfixRequest)->Result<(),Error>{
|
||||
// download the location of the map model
|
||||
let location=self.cloud_context.get_asset_version_location(rbx_asset::cloud::GetAssetVersionRequest{
|
||||
asset_id:upload_info.ModelID,
|
||||
version:Some(upload_info.ModelVersion),
|
||||
}).await.map_err(UploadError::Get)?;
|
||||
version:upload_info.ModelVersion,
|
||||
}).await.map_err(Error::GetLocation)?;
|
||||
|
||||
// if the location does not exist, you are not allowed to donwload it
|
||||
let Some(location)=location.location else{
|
||||
return Err(Error::NonFreeModel);
|
||||
};
|
||||
|
||||
// download the map model
|
||||
let model_data=self.cloud_context.get_asset(&location).await.map_err(Error::Get)?;
|
||||
|
||||
// upload the map to the strafesnet group
|
||||
let _upload_response=self.roblox_cookie.upload(rbx_asset::cookie::UploadRequest{
|
||||
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).await.map_err(UploadError::Upload)?;
|
||||
},model_data).await.map_err(Error::Upload)?;
|
||||
|
||||
// that's it, the database entry does not need to be changed.
|
||||
|
||||
//TEMP
|
||||
return Err(UploadError::Unimplemented);
|
||||
|
||||
// mark submission as uploaded, TargetAssetID is unchanged
|
||||
self.api_internal.action_submission_uploaded(submissions_api::types::ActionSubmissionUploadedRequest{
|
||||
SubmissionID:upload_info.SubmissionID,
|
||||
UploadedAssetID:0, //TEMP
|
||||
}).await.map_err(UploadError::ApiActionSubmissionUploaded)?;
|
||||
// mark mapfix as uploaded, TargetAssetID is unchanged
|
||||
self.api.action_mapfix_uploaded(submissions_api::types::ActionMapfixUploadedRequest{
|
||||
MapfixID:upload_info.MapfixID,
|
||||
}).await.map_err(Error::ApiActionMapfixUploaded)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,59 +1,53 @@
|
||||
use crate::nats_types::UploadNewRequest;
|
||||
use crate::nats_types::UploadSubmissionRequest;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum UploadError{
|
||||
Get(rbx_asset::cookie::GetError),
|
||||
pub enum Error{
|
||||
GetLocation(rbx_asset::cloud::GetError),
|
||||
NonFreeModel,
|
||||
Get(rbx_asset::cloud::GetError),
|
||||
Json(serde_json::Error),
|
||||
Create(rbx_asset::cookie::CreateError),
|
||||
SystemTime(std::time::SystemTimeError),
|
||||
ApiActionSubmissionUploaded(submissions_api::Error),
|
||||
}
|
||||
impl std::fmt::Display for UploadError{
|
||||
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 UploadError{}
|
||||
impl std::error::Error for Error{}
|
||||
|
||||
pub struct Uploader{
|
||||
roblox_cookie:rbx_asset::cookie::CookieContext,
|
||||
group_id:Option<u64>,
|
||||
api:submissions_api::internal::Context,
|
||||
}
|
||||
impl Uploader{
|
||||
pub const fn new(
|
||||
roblox_cookie:rbx_asset::cookie::CookieContext,
|
||||
group_id:Option<u64>,
|
||||
api:submissions_api::internal::Context,
|
||||
)->Self{
|
||||
Self{
|
||||
roblox_cookie,
|
||||
group_id,
|
||||
api,
|
||||
}
|
||||
}
|
||||
pub async fn upload(&self,upload_info:UploadNewRequest)->Result<(),UploadError>{
|
||||
// download the map model version
|
||||
let model_data=self.roblox_cookie.get_asset(rbx_asset::cookie::GetAssetRequest{
|
||||
impl crate::message_handler::MessageHandler{
|
||||
pub async fn upload_submission(&self,upload_info:UploadSubmissionRequest)->Result<(),Error>{
|
||||
// download the location of the map model
|
||||
let location=self.cloud_context.get_asset_version_location(rbx_asset::cloud::GetAssetVersionRequest{
|
||||
asset_id:upload_info.ModelID,
|
||||
version:Some(upload_info.ModelVersion),
|
||||
}).await.map_err(UploadError::Get)?;
|
||||
version:upload_info.ModelVersion,
|
||||
}).await.map_err(Error::GetLocation)?;
|
||||
|
||||
// if the location does not exist, you are not allowed to donwload it
|
||||
let Some(location)=location.location else{
|
||||
return Err(Error::NonFreeModel);
|
||||
};
|
||||
|
||||
// download the map model
|
||||
let model_data=self.cloud_context.get_asset(&location).await.map_err(Error::Get)?;
|
||||
|
||||
// upload the map to the strafesnet group
|
||||
let upload_response=self.roblox_cookie.create(rbx_asset::cookie::CreateRequest{
|
||||
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(UploadError::Create)?;
|
||||
},model_data).await.map_err(Error::Create)?;
|
||||
|
||||
// note the asset id of the created model for later release, and mark the submission as uploaded
|
||||
self.api.action_submission_uploaded(submissions_api::types::ActionSubmissionUploadedRequest{
|
||||
SubmissionID:upload_info.SubmissionID,
|
||||
UploadedAssetID:upload_response.AssetId,
|
||||
}).await.map_err(UploadError::ApiActionSubmissionUploaded)?;
|
||||
}).await.map_err(Error::ApiActionSubmissionUploaded)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
39
validation/src/validate_mapfix.rs
Normal file
39
validation/src/validate_mapfix.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use crate::nats_types::ValidateMapfixRequest;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
ApiActionMapfixValidate(submissions_api::Error),
|
||||
}
|
||||
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 validate_mapfix(&self,validate_info:ValidateMapfixRequest)->Result<(),Error>{
|
||||
let mapfix_id=validate_info.MapfixID;
|
||||
let validate_result=self.validate_inner(validate_info.into()).await;
|
||||
|
||||
// update the mapfix depending on the result
|
||||
match &validate_result{
|
||||
Ok(())=>{
|
||||
// update the mapfix model status to validated
|
||||
self.api.action_mapfix_validated(
|
||||
submissions_api::types::MapfixID(mapfix_id)
|
||||
).await.map_err(Error::ApiActionMapfixValidate)?;
|
||||
},
|
||||
Err(e)=>{
|
||||
// update the mapfix model status to accepted
|
||||
self.api.action_mapfix_accepted(submissions_api::types::ActionMapfixAcceptedRequest{
|
||||
MapfixID:mapfix_id,
|
||||
StatusMessage:format!("{e}"),
|
||||
}).await.map_err(Error::ApiActionMapfixValidate)?;
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
39
validation/src/validate_submission.rs
Normal file
39
validation/src/validate_submission.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use crate::nats_types::ValidateSubmissionRequest;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
ApiActionSubmissionValidate(submissions_api::Error),
|
||||
}
|
||||
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 validate_submission(&self,validate_info:ValidateSubmissionRequest)->Result<(),Error>{
|
||||
let submission_id=validate_info.SubmissionID;
|
||||
let validate_result=self.validate_inner(validate_info.into()).await;
|
||||
|
||||
// update the submission depending on the result
|
||||
match &validate_result{
|
||||
Ok(())=>{
|
||||
// update the submission model status to validated
|
||||
self.api.action_submission_validated(
|
||||
submissions_api::types::SubmissionID(submission_id)
|
||||
).await.map_err(Error::ApiActionSubmissionValidate)?;
|
||||
},
|
||||
Err(e)=>{
|
||||
// update the submission model status to accepted
|
||||
self.api.action_submission_accepted(submissions_api::types::ActionSubmissionAcceptedRequest{
|
||||
SubmissionID:submission_id,
|
||||
StatusMessage:format!("{e}"),
|
||||
}).await.map_err(Error::ApiActionSubmissionValidate)?;
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
use futures::TryStreamExt;
|
||||
use submissions_api::types::ResourceType;
|
||||
|
||||
use crate::nats_types::ValidateRequest;
|
||||
use crate::rbx_util::{class_is_a,read_dom,ReadDomError};
|
||||
use crate::types::ResourceID;
|
||||
|
||||
const SCRIPT_CONCURRENCY:usize=16;
|
||||
|
||||
@@ -30,79 +32,81 @@ fn hash_source(source:&str)->String{
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum ValidateError{
|
||||
pub enum Error{
|
||||
ScriptFlaggedIllegalKeyword(String),
|
||||
ScriptBlocked(Option<submissions_api::types::ScriptID>),
|
||||
ScriptNotYetReviewed(Option<submissions_api::types::ScriptID>),
|
||||
ModelFileDownload(rbx_asset::cookie::GetError),
|
||||
ModelLocationDownload(rbx_asset::cloud::GetError),
|
||||
NonFreeModel,
|
||||
ModelFileDownload(rbx_asset::cloud::GetError),
|
||||
ModelFileDecode(ReadDomError),
|
||||
ApiGetScriptPolicyFromHash(submissions_api::types::SingleItemError),
|
||||
ApiGetScript(submissions_api::Error),
|
||||
ApiCreateScript(submissions_api::Error),
|
||||
ApiCreateScriptPolicy(submissions_api::Error),
|
||||
ApiGetScriptFromHash(submissions_api::types::SingleItemError),
|
||||
ApiUpdateMapfixModel(submissions_api::Error),
|
||||
ApiUpdateSubmissionModel(submissions_api::Error),
|
||||
ApiActionSubmissionValidate(submissions_api::Error),
|
||||
ModelFileRootMustHaveOneChild,
|
||||
ModelFileChildRefIsNil,
|
||||
ModelFileEncode(rbx_binary::EncodeError),
|
||||
AssetUpload(rbx_asset::cookie::UploadError),
|
||||
AssetCreate(rbx_asset::cookie::CreateError),
|
||||
}
|
||||
impl std::fmt::Display for ValidateError{
|
||||
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 ValidateError{}
|
||||
impl std::error::Error for Error{}
|
||||
|
||||
pub struct Validator{
|
||||
roblox_cookie:rbx_asset::cookie::CookieContext,
|
||||
api:submissions_api::internal::Context,
|
||||
#[allow(nonstandard_style)]
|
||||
pub struct ValidateRequest{
|
||||
pub ModelID:u64,
|
||||
pub ModelVersion:u64,
|
||||
pub ValidatedModelID:Option<u64>,
|
||||
pub ResourceID:ResourceID,
|
||||
}
|
||||
|
||||
impl Validator{
|
||||
pub const fn new(
|
||||
roblox_cookie:rbx_asset::cookie::CookieContext,
|
||||
api:submissions_api::internal::Context,
|
||||
)->Self{
|
||||
impl From<crate::nats_types::ValidateMapfixRequest> for ValidateRequest{
|
||||
fn from(value:crate::nats_types::ValidateMapfixRequest)->Self{
|
||||
Self{
|
||||
roblox_cookie,
|
||||
api,
|
||||
ModelID:value.ModelID,
|
||||
ModelVersion:value.ModelVersion,
|
||||
ValidatedModelID:value.ValidatedModelID,
|
||||
ResourceID:ResourceID::Mapfix(value.MapfixID),
|
||||
}
|
||||
}
|
||||
pub async fn validate(&self,validate_info:ValidateRequest)->Result<(),ValidateError>{
|
||||
let submission_id=validate_info.SubmissionID;
|
||||
let validate_result=self.validate_inner(validate_info).await;
|
||||
|
||||
// update the submission depending on the result
|
||||
match &validate_result{
|
||||
Ok(())=>{
|
||||
// update the submission model status to validated
|
||||
self.api.action_submission_validated(
|
||||
submissions_api::types::SubmissionID(submission_id)
|
||||
).await.map_err(ValidateError::ApiActionSubmissionValidate)?;
|
||||
},
|
||||
Err(e)=>{
|
||||
// update the submission model status to accepted
|
||||
self.api.action_submission_accepted(submissions_api::types::ActionSubmissionAcceptedRequest{
|
||||
SubmissionID:submission_id,
|
||||
StatusMessage:format!("{e}"),
|
||||
}).await.map_err(ValidateError::ApiActionSubmissionValidate)?;
|
||||
},
|
||||
}
|
||||
impl From<crate::nats_types::ValidateSubmissionRequest> for ValidateRequest{
|
||||
fn from(value:crate::nats_types::ValidateSubmissionRequest)->Self{
|
||||
Self{
|
||||
ModelID:value.ModelID,
|
||||
ModelVersion:value.ModelVersion,
|
||||
ValidatedModelID:value.ValidatedModelID,
|
||||
ResourceID:ResourceID::Submission(value.SubmissionID),
|
||||
}
|
||||
|
||||
validate_result
|
||||
}
|
||||
pub async fn validate_inner(&self,validate_info:ValidateRequest)->Result<(),ValidateError>{
|
||||
// download map
|
||||
let data=self.roblox_cookie.get_asset(rbx_asset::cookie::GetAssetRequest{
|
||||
}
|
||||
|
||||
impl crate::message_handler::MessageHandler{
|
||||
pub async fn validate_inner(&self,validate_info:ValidateRequest)->Result<(),Error>{
|
||||
// download the location of the map model
|
||||
let location=self.cloud_context.get_asset_version_location(rbx_asset::cloud::GetAssetVersionRequest{
|
||||
asset_id:validate_info.ModelID,
|
||||
version:Some(validate_info.ModelVersion),
|
||||
}).await.map_err(ValidateError::ModelFileDownload)?;
|
||||
version:validate_info.ModelVersion,
|
||||
}).await.map_err(Error::ModelLocationDownload)?;
|
||||
|
||||
// if the location does not exist, you are not allowed to donwload it
|
||||
let Some(location)=location.location else{
|
||||
return Err(Error::NonFreeModel);
|
||||
};
|
||||
|
||||
// download the map model
|
||||
let model_data=self.cloud_context.get_asset(&location).await.map_err(Error::ModelFileDownload)?;
|
||||
|
||||
// decode dom (slow!)
|
||||
let mut dom=read_dom(&mut std::io::Cursor::new(data)).map_err(ValidateError::ModelFileDecode)?;
|
||||
let mut dom=read_dom(std::io::Cursor::new(model_data)).map_err(Error::ModelFileDecode)?;
|
||||
|
||||
/* VALIDATE MAP */
|
||||
|
||||
@@ -117,7 +121,7 @@ impl Validator{
|
||||
// immediately abort
|
||||
// grab path to offending script
|
||||
let path=get_partial_path(&dom,script);
|
||||
return Err(ValidateError::ScriptFlaggedIllegalKeyword(path));
|
||||
return Err(Error::ScriptFlaggedIllegalKeyword(path));
|
||||
}
|
||||
// associate a name and policy with the source code
|
||||
// policy will be fetched from the database to replace the default policy
|
||||
@@ -138,7 +142,7 @@ impl Validator{
|
||||
// fetch the script policy
|
||||
let script_policy=self.api.get_script_policy_from_hash(submissions_api::types::HashRequest{
|
||||
hash:hash.as_str(),
|
||||
}).await.map_err(ValidateError::ApiGetScriptPolicyFromHash)?;
|
||||
}).await.map_err(Error::ApiGetScriptPolicyFromHash)?;
|
||||
|
||||
// write the policy to the script_map, fetching the replacement code if necessary
|
||||
if let Some(script_policy)=script_policy{
|
||||
@@ -150,24 +154,30 @@ impl Validator{
|
||||
submissions_api::types::Policy::Replace=>{
|
||||
let script=self.api.get_script(submissions_api::types::GetScriptRequest{
|
||||
ScriptID:script_policy.ToScriptID,
|
||||
}).await.map_err(ValidateError::ApiGetScript)?;
|
||||
}).await.map_err(Error::ApiGetScript)?;
|
||||
Policy::Replace(script.Source)
|
||||
},
|
||||
};
|
||||
}else{
|
||||
let (resource_type,resource_id)=match validate_info.ResourceID{
|
||||
ResourceID::Mapfix(mapfix_id)=>(ResourceType::Mapfix,mapfix_id),
|
||||
ResourceID::Submission(submission_id)=>(ResourceType::Submission,submission_id),
|
||||
};
|
||||
|
||||
// upload the script
|
||||
let script=self.api.create_script(submissions_api::types::CreateScriptRequest{
|
||||
Name:name.as_str(),
|
||||
Source:source.as_str(),
|
||||
SubmissionID:Some(validate_info.SubmissionID),
|
||||
}).await.map_err(ValidateError::ApiCreateScript)?;
|
||||
ResourceType:resource_type,
|
||||
ResourceID:Some(resource_id),
|
||||
}).await.map_err(Error::ApiCreateScript)?;
|
||||
|
||||
// create a None policy (pending review by yours truly)
|
||||
self.api.create_script_policy(submissions_api::types::CreateScriptPolicyRequest{
|
||||
ToScriptID:script.ID,
|
||||
FromScriptID:script.ID,
|
||||
ToScriptID:script.ScriptID,
|
||||
FromScriptID:script.ScriptID,
|
||||
Policy:submissions_api::types::Policy::None,
|
||||
}).await.map_err(ValidateError::ApiCreateScriptPolicy)?;
|
||||
}).await.map_err(Error::ApiCreateScriptPolicy)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -175,7 +185,7 @@ impl Validator{
|
||||
.await?;
|
||||
|
||||
// make the replacements
|
||||
let mut modified=true;
|
||||
let mut modified=false;
|
||||
for &script_ref in &script_refs{
|
||||
if let Some(script)=dom.get_by_ref_mut(script_ref){
|
||||
if let Some(rbx_dom_weak::types::Variant::String(source))=script.properties.get_mut("Source"){
|
||||
@@ -184,8 +194,8 @@ impl Validator{
|
||||
let hash=hash_source(source.as_str());
|
||||
let script=self.api.get_script_from_hash(submissions_api::types::HashRequest{
|
||||
hash:hash.as_str(),
|
||||
}).await.map_err(ValidateError::ApiGetScriptFromHash)?;
|
||||
return Err(ValidateError::ScriptBlocked(script.map(|s|s.ID)));
|
||||
}).await.map_err(Error::ApiGetScriptFromHash)?;
|
||||
return Err(Error::ScriptBlocked(script.map(|s|s.ID)));
|
||||
},
|
||||
None
|
||||
|Some(Policy::None)
|
||||
@@ -193,8 +203,8 @@ impl Validator{
|
||||
let hash=hash_source(source.as_str());
|
||||
let script=self.api.get_script_from_hash(submissions_api::types::HashRequest{
|
||||
hash:hash.as_str(),
|
||||
}).await.map_err(ValidateError::ApiGetScriptFromHash)?;
|
||||
return Err(ValidateError::ScriptNotYetReviewed(script.map(|s|s.ID)));
|
||||
}).await.map_err(Error::ApiGetScriptFromHash)?;
|
||||
return Err(Error::ScriptNotYetReviewed(script.map(|s|s.ID)));
|
||||
},
|
||||
Some(Policy::Allowed)=>(),
|
||||
Some(Policy::Delete)=>{
|
||||
@@ -211,104 +221,71 @@ impl Validator{
|
||||
}
|
||||
}
|
||||
|
||||
println!("[Validator] Forcing model upload! modified=true");
|
||||
|
||||
// if the model was validated, the submission must be changed to use the modified model
|
||||
if modified{
|
||||
let (validated_model_id,validated_model_version)=if modified{
|
||||
// serialize model (slow!)
|
||||
let mut data=Vec::new();
|
||||
let &[map_ref]=dom.root().children()else{
|
||||
return Err(ValidateError::ModelFileRootMustHaveOneChild);
|
||||
return Err(Error::ModelFileRootMustHaveOneChild);
|
||||
};
|
||||
rbx_binary::to_writer(&mut data,&dom,&[map_ref]).map_err(ValidateError::ModelFileEncode)?;
|
||||
rbx_binary::to_writer(&mut data,&dom,&[map_ref]).map_err(Error::ModelFileEncode)?;
|
||||
|
||||
// upload a model lol
|
||||
let model_id=if let Some(model_id)=validate_info.ValidatedModelID{
|
||||
if let Some(model_id)=validate_info.ValidatedModelID{
|
||||
// upload to existing id
|
||||
let response=self.roblox_cookie.upload(rbx_asset::cookie::UploadRequest{
|
||||
let response=self.cookie_context.upload(rbx_asset::cookie::UploadRequest{
|
||||
assetid:model_id,
|
||||
name:None,
|
||||
description:None,
|
||||
ispublic:None,
|
||||
allowComments:None,
|
||||
groupId:None,
|
||||
},data).await.map_err(ValidateError::AssetUpload)?;
|
||||
},data).await.map_err(Error::AssetUpload)?;
|
||||
|
||||
response.AssetId
|
||||
(response.AssetId,response.AssetVersion)
|
||||
}else{
|
||||
// grab the map instance from the map re
|
||||
// grab the map instance from the map ref
|
||||
let Some(map_instance)=dom.get_by_ref(map_ref)else{
|
||||
return Err(ValidateError::ModelFileChildRefIsNil);
|
||||
return Err(Error::ModelFileChildRefIsNil);
|
||||
};
|
||||
// create new model
|
||||
let response=self.roblox_cookie.create(rbx_asset::cookie::CreateRequest{
|
||||
let response=self.cookie_context.create(rbx_asset::cookie::CreateRequest{
|
||||
name:map_instance.name.clone(),
|
||||
description:"".to_owned(),
|
||||
ispublic:true,
|
||||
allowComments:true,
|
||||
groupId:None,
|
||||
},data).await.map_err(ValidateError::AssetCreate)?;
|
||||
},data).await.map_err(Error::AssetCreate)?;
|
||||
|
||||
response.AssetId
|
||||
};
|
||||
|
||||
// update the submission to use the validated model
|
||||
self.api.update_submission_validated_model(submissions_api::types::UpdateSubmissionModelRequest{
|
||||
SubmissionID:validate_info.SubmissionID,
|
||||
ModelID:model_id,
|
||||
ModelVersion:1, //TODO
|
||||
}).await.map_err(ValidateError::ApiUpdateSubmissionModel)?;
|
||||
(response.AssetId,response.AssetVersion)
|
||||
}
|
||||
}else{
|
||||
(validate_info.ModelID,validate_info.ModelVersion)
|
||||
};
|
||||
|
||||
match validate_info.ResourceID{
|
||||
ResourceID::Mapfix(mapfix_id)=>{
|
||||
// update the mapfix to use the validated model
|
||||
self.api.update_mapfix_validated_model(submissions_api::types::UpdateMapfixModelRequest{
|
||||
MapfixID:mapfix_id,
|
||||
ModelID:validated_model_id,
|
||||
ModelVersion:validated_model_version,
|
||||
}).await.map_err(Error::ApiUpdateMapfixModel)?;
|
||||
},
|
||||
ResourceID::Submission(submission_id)=>{
|
||||
// update the submission to use the validated model
|
||||
self.api.update_submission_validated_model(submissions_api::types::UpdateSubmissionModelRequest{
|
||||
SubmissionID:submission_id,
|
||||
ModelID:validated_model_id,
|
||||
ModelVersion:validated_model_version,
|
||||
}).await.map_err(Error::ApiUpdateSubmissionModel)?;
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum ReadDomError{
|
||||
Binary(rbx_binary::DecodeError),
|
||||
Xml(rbx_xml::DecodeError),
|
||||
Read(std::io::Error),
|
||||
Seek(std::io::Error),
|
||||
UnknownFormat([u8;8]),
|
||||
}
|
||||
impl std::fmt::Display for ReadDomError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for ReadDomError{}
|
||||
|
||||
fn read_dom<R:std::io::Read+std::io::Seek>(input:&mut R)->Result<rbx_dom_weak::WeakDom,ReadDomError>{
|
||||
let mut first_8=[0u8;8];
|
||||
std::io::Read::read_exact(input,&mut first_8).map_err(ReadDomError::Read)?;
|
||||
std::io::Seek::rewind(input).map_err(ReadDomError::Seek)?;
|
||||
match &first_8[0..4]{
|
||||
b"<rob"=>{
|
||||
match &first_8[4..8]{
|
||||
b"lox!"=>rbx_binary::from_reader(input).map_err(ReadDomError::Binary),
|
||||
b"lox "=>rbx_xml::from_reader(input,rbx_xml::DecodeOptions::default()).map_err(ReadDomError::Xml),
|
||||
_=>Err(ReadDomError::UnknownFormat(first_8)),
|
||||
}
|
||||
},
|
||||
_=>Err(ReadDomError::UnknownFormat(first_8)),
|
||||
}
|
||||
}
|
||||
|
||||
fn class_is_a(class:&str,superclass:&str)->bool{
|
||||
if class==superclass{
|
||||
return true
|
||||
}
|
||||
let class_descriptor=rbx_reflection_database::get().classes.get(class);
|
||||
if let Some(descriptor)=&class_descriptor{
|
||||
if let Some(class_super)=&descriptor.superclass{
|
||||
return class_is_a(&class_super,superclass)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn recursive_collect_superclass(objects:&mut std::vec::Vec<rbx_dom_weak::types::Ref>,dom:&rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance,superclass:&str){
|
||||
for &referent in instance.children(){
|
||||
if let Some(c)=dom.get_by_ref(referent){
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM oven/bun:latest
|
||||
FROM registry.itzana.me/docker-proxy/oven/bun:1.2.8
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -10,4 +10,4 @@ ENV NEXT_TELEMETRY_DISABLED=1
|
||||
|
||||
RUN bun install
|
||||
RUN bun run build
|
||||
ENTRYPOINT ["bun", "run", "start"]
|
||||
ENTRYPOINT ["bun", "run", "start"]
|
||||
|
||||
886
web/bun.lock
Normal file
886
web/bun.lock
Normal file
@@ -0,0 +1,886 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "map-service-web",
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.0",
|
||||
"@mui/icons-material": "^6.1.10",
|
||||
"@mui/material": "^6.1.10",
|
||||
"next": "^15.1.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"sass": "^1.82.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@types/node": "^20.17.9",
|
||||
"@types/react": "^19.0.1",
|
||||
"@types/react-dom": "^19.0.2",
|
||||
"eslint": "^9.16.0",
|
||||
"eslint-config-next": "15.1.0",
|
||||
"typescript": "^5.7.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="],
|
||||
|
||||
"@babel/generator": ["@babel/generator@7.27.0", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/types": "^7.27.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw=="],
|
||||
|
||||
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw=="],
|
||||
|
||||
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.9", "", {}, "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="],
|
||||
|
||||
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="],
|
||||
|
||||
"@babel/parser": ["@babel/parser@7.27.0", "", { "dependencies": { "@babel/types": "^7.27.0" }, "bin": "./bin/babel-parser.js" }, "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg=="],
|
||||
|
||||
"@babel/runtime": ["@babel/runtime@7.27.0", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw=="],
|
||||
|
||||
"@babel/template": ["@babel/template@7.27.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/parser": "^7.27.0", "@babel/types": "^7.27.0" } }, "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA=="],
|
||||
|
||||
"@babel/traverse": ["@babel/traverse@7.27.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.27.0", "@babel/parser": "^7.27.0", "@babel/template": "^7.27.0", "@babel/types": "^7.27.0", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA=="],
|
||||
|
||||
"@babel/types": ["@babel/types@7.27.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg=="],
|
||||
|
||||
"@emnapi/core": ["@emnapi/core@1.4.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.1", "tslib": "^2.4.0" } }, "sha512-H+N/FqT07NmLmt6OFFtDfwe8PNygprzBikrEMyQfgqSmT0vzE515Pz7R8izwB9q/zsH/MA64AKoul3sA6/CzVg=="],
|
||||
|
||||
"@emnapi/runtime": ["@emnapi/runtime@1.4.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-64WYIf4UYcdLnbKn/umDlNjQDSS8AgZrI/R9+x5ilkUVFxXcA1Ebl+gQLc/6mERA4407Xof0R7wEyEuj091CVw=="],
|
||||
|
||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw=="],
|
||||
|
||||
"@emotion/babel-plugin": ["@emotion/babel-plugin@11.13.5", "", { "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/serialize": "^1.3.3", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", "stylis": "4.2.0" } }, "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ=="],
|
||||
|
||||
"@emotion/cache": ["@emotion/cache@11.14.0", "", { "dependencies": { "@emotion/memoize": "^0.9.0", "@emotion/sheet": "^1.4.0", "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } }, "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA=="],
|
||||
|
||||
"@emotion/hash": ["@emotion/hash@0.9.2", "", {}, "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="],
|
||||
|
||||
"@emotion/is-prop-valid": ["@emotion/is-prop-valid@1.3.1", "", { "dependencies": { "@emotion/memoize": "^0.9.0" } }, "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw=="],
|
||||
|
||||
"@emotion/memoize": ["@emotion/memoize@0.9.0", "", {}, "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="],
|
||||
|
||||
"@emotion/react": ["@emotion/react@11.14.0", "", { "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/cache": "^11.14.0", "@emotion/serialize": "^1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA=="],
|
||||
|
||||
"@emotion/serialize": ["@emotion/serialize@1.3.3", "", { "dependencies": { "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/unitless": "^0.10.0", "@emotion/utils": "^1.4.2", "csstype": "^3.0.2" } }, "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA=="],
|
||||
|
||||
"@emotion/sheet": ["@emotion/sheet@1.4.0", "", {}, "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg=="],
|
||||
|
||||
"@emotion/styled": ["@emotion/styled@11.14.0", "", { "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/is-prop-valid": "^1.3.0", "@emotion/serialize": "^1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", "@emotion/utils": "^1.4.2" }, "peerDependencies": { "@emotion/react": "^11.0.0-rc.0", "react": ">=16.8.0" } }, "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA=="],
|
||||
|
||||
"@emotion/unitless": ["@emotion/unitless@0.10.0", "", {}, "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg=="],
|
||||
|
||||
"@emotion/use-insertion-effect-with-fallbacks": ["@emotion/use-insertion-effect-with-fallbacks@1.2.0", "", { "peerDependencies": { "react": ">=16.8.0" } }, "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg=="],
|
||||
|
||||
"@emotion/utils": ["@emotion/utils@1.4.2", "", {}, "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA=="],
|
||||
|
||||
"@emotion/weak-memoize": ["@emotion/weak-memoize@0.4.0", "", {}, "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="],
|
||||
|
||||
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.5.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w=="],
|
||||
|
||||
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="],
|
||||
|
||||
"@eslint/config-array": ["@eslint/config-array@0.19.2", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w=="],
|
||||
|
||||
"@eslint/config-helpers": ["@eslint/config-helpers@0.2.1", "", {}, "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw=="],
|
||||
|
||||
"@eslint/core": ["@eslint/core@0.12.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg=="],
|
||||
|
||||
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="],
|
||||
|
||||
"@eslint/js": ["@eslint/js@9.23.0", "", {}, "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw=="],
|
||||
|
||||
"@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="],
|
||||
|
||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.8", "", { "dependencies": { "@eslint/core": "^0.13.0", "levn": "^0.4.1" } }, "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA=="],
|
||||
|
||||
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
||||
|
||||
"@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="],
|
||||
|
||||
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
|
||||
|
||||
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.2", "", {}, "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ=="],
|
||||
|
||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
|
||||
|
||||
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="],
|
||||
|
||||
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="],
|
||||
|
||||
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="],
|
||||
|
||||
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="],
|
||||
|
||||
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="],
|
||||
|
||||
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="],
|
||||
|
||||
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="],
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="],
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="],
|
||||
|
||||
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="],
|
||||
|
||||
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="],
|
||||
|
||||
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="],
|
||||
|
||||
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="],
|
||||
|
||||
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="],
|
||||
|
||||
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="],
|
||||
|
||||
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="],
|
||||
|
||||
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="],
|
||||
|
||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="],
|
||||
|
||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||
|
||||
"@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="],
|
||||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="],
|
||||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="],
|
||||
|
||||
"@mui/core-downloads-tracker": ["@mui/core-downloads-tracker@6.4.10", "", {}, "sha512-cblGjlM6+xsptwyaALw8RbRIUoqmKxOqLxlk2LkTDhxqUuql1YSOKKLH3w+Yd2QLz28b7MR65sx1OjsRZUfOSQ=="],
|
||||
|
||||
"@mui/icons-material": ["@mui/icons-material@6.4.10", "", { "dependencies": { "@babel/runtime": "^7.26.0" }, "peerDependencies": { "@mui/material": "^6.4.10", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-c2KdFl4KZ0QYC+JSDTMCNjcuOL2rVSdIx/beo7FwJDh2e9XqC1MoLCjw6L1Jo40zbArkgJyg3oFORbXcRfgZOA=="],
|
||||
|
||||
"@mui/material": ["@mui/material@6.4.10", "", { "dependencies": { "@babel/runtime": "^7.26.0", "@mui/core-downloads-tracker": "^6.4.10", "@mui/system": "^6.4.10", "@mui/types": "~7.2.24", "@mui/utils": "^6.4.9", "@popperjs/core": "^2.11.8", "@types/react-transition-group": "^4.4.12", "clsx": "^2.1.1", "csstype": "^3.1.3", "prop-types": "^15.8.1", "react-is": "^19.0.0", "react-transition-group": "^4.4.5" }, "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", "@mui/material-pigment-css": "^6.4.10", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/react", "@emotion/styled", "@mui/material-pigment-css", "@types/react"] }, "sha512-L1B0+Vg9NFjo3NcfODH3bohl6fIkzjyDBHBHb3Al4QI7owaJrFm2sSDyfz++iatzICug6U6q5tHLQrCLO71xkg=="],
|
||||
|
||||
"@mui/private-theming": ["@mui/private-theming@6.4.9", "", { "dependencies": { "@babel/runtime": "^7.26.0", "@mui/utils": "^6.4.9", "prop-types": "^15.8.1" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-LktcVmI5X17/Q5SkwjCcdOLBzt1hXuc14jYa7NPShog0GBDCDvKtcnP0V7a2s6EiVRlv7BzbWEJzH6+l/zaCxw=="],
|
||||
|
||||
"@mui/styled-engine": ["@mui/styled-engine@6.4.9", "", { "dependencies": { "@babel/runtime": "^7.26.0", "@emotion/cache": "^11.13.5", "@emotion/serialize": "^1.3.3", "@emotion/sheet": "^1.4.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "peerDependencies": { "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/react", "@emotion/styled"] }, "sha512-qZRWO0cT407NI4ZRjZcH+1SOu8f3JzLHqdMlg52GyEufM9pkSZFnf7xjpwnlvkixcGjco6wLlMD0VB43KRcBuA=="],
|
||||
|
||||
"@mui/system": ["@mui/system@6.4.10", "", { "dependencies": { "@babel/runtime": "^7.26.0", "@mui/private-theming": "^6.4.9", "@mui/styled-engine": "^6.4.9", "@mui/types": "~7.2.24", "@mui/utils": "^6.4.9", "clsx": "^2.1.1", "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/react", "@emotion/styled", "@types/react"] }, "sha512-RyBGQwP3tgo4JEibK+RwVu1a6nQ6y8urMCNsb2aiN/nvTxxumq6P26aoG4GTUf8L4O1sthC4lMXlP4r8ixDkMg=="],
|
||||
|
||||
"@mui/types": ["@mui/types@7.2.24", "", { "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw=="],
|
||||
|
||||
"@mui/utils": ["@mui/utils@6.4.9", "", { "dependencies": { "@babel/runtime": "^7.26.0", "@mui/types": "~7.2.24", "@types/prop-types": "^15.7.14", "clsx": "^2.1.1", "prop-types": "^15.8.1", "react-is": "^19.0.0" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-Y12Q9hbK9g+ZY0T3Rxrx9m2m10gaphDuUMgWxyV5kNJevVxXYCLclYUCC9vXaIk1/NdNDTcW2Yfr2OGvNFNmHg=="],
|
||||
|
||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.8", "", { "dependencies": { "@emnapi/core": "^1.4.0", "@emnapi/runtime": "^1.4.0", "@tybys/wasm-util": "^0.9.0" } }, "sha512-OBlgKdX7gin7OIq4fadsjpg+cp2ZphvAIKucHsNfTdJiqdOmOEwQd/bHi0VwNrcw5xpBJyUw6cK/QilCqy1BSg=="],
|
||||
|
||||
"@next/env": ["@next/env@15.2.4", "", {}, "sha512-+SFtMgoiYP3WoSswuNmxJOCwi06TdWE733D+WPjpXIe4LXGULwEaofiiAy6kbS0+XjM5xF5n3lKuBwN2SnqD9g=="],
|
||||
|
||||
"@next/eslint-plugin-next": ["@next/eslint-plugin-next@15.1.0", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-+jPT0h+nelBT6HC9ZCHGc7DgGVy04cv4shYdAe6tKlEbjQUtwU3LzQhzbDHQyY2m6g39m6B0kOFVuLGBrxxbGg=="],
|
||||
|
||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-1AnMfs655ipJEDC/FHkSr0r3lXBgpqKo4K1kiwfUf3iE68rDFXZ1TtHdMvf7D0hMItgDZ7Vuq3JgNMbt/+3bYw=="],
|
||||
|
||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-3qK2zb5EwCwxnO2HeO+TRqCubeI/NgCe+kL5dTJlPldV/uwCnUgC7VbEzgmxbfrkbjehL4H9BPztWOEtsoMwew=="],
|
||||
|
||||
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-HFN6GKUcrTWvem8AZN7tT95zPb0GUGv9v0d0iyuTb303vbXkkbHDp/DxufB04jNVD+IN9yHy7y/6Mqq0h0YVaQ=="],
|
||||
|
||||
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-Oioa0SORWLwi35/kVB8aCk5Uq+5/ZIumMK1kJV+jSdazFm2NzPDztsefzdmzzpx5oGCJ6FkUC7vkaUseNTStNA=="],
|
||||
|
||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-yb5WTRaHdkgOqFOZiu6rHV1fAEK0flVpaIN2HB6kxHVSy/dIajWbThS7qON3W9/SNOH2JWkVCyulgGYekMePuw=="],
|
||||
|
||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-Dcdv/ix6srhkM25fgXiyOieFUkz+fOYkHlydWCtB0xMST6X9XYI3yPDKBZt1xuhOytONsIFJFB08xXYsxUwJLw=="],
|
||||
|
||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.2.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-dW0i7eukvDxtIhCYkMrZNQfNicPDExt2jPb9AZPpL7cfyUo7QSNl1DjsHjmmKp6qNAqUESyT8YFl/Aw91cNJJg=="],
|
||||
|
||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.2.4", "", { "os": "win32", "cpu": "x64" }, "sha512-SbnWkJmkS7Xl3kre8SdMF6F/XDh1DTFEhp0jRTj/uB8iPKoU2bb2NDfcu+iifv1+mxQEd1g2vvSxcZbXSKyWiQ=="],
|
||||
|
||||
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
||||
|
||||
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
|
||||
|
||||
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
||||
|
||||
"@nolyfill/is-core-module": ["@nolyfill/is-core-module@1.0.39", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="],
|
||||
|
||||
"@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="],
|
||||
|
||||
"@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.1", "", { "os": "android", "cpu": "arm64" }, "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA=="],
|
||||
|
||||
"@parcel/watcher-darwin-arm64": ["@parcel/watcher-darwin-arm64@2.5.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw=="],
|
||||
|
||||
"@parcel/watcher-darwin-x64": ["@parcel/watcher-darwin-x64@2.5.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg=="],
|
||||
|
||||
"@parcel/watcher-freebsd-x64": ["@parcel/watcher-freebsd-x64@2.5.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ=="],
|
||||
|
||||
"@parcel/watcher-linux-arm-glibc": ["@parcel/watcher-linux-arm-glibc@2.5.1", "", { "os": "linux", "cpu": "arm" }, "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA=="],
|
||||
|
||||
"@parcel/watcher-linux-arm-musl": ["@parcel/watcher-linux-arm-musl@2.5.1", "", { "os": "linux", "cpu": "arm" }, "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q=="],
|
||||
|
||||
"@parcel/watcher-linux-arm64-glibc": ["@parcel/watcher-linux-arm64-glibc@2.5.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w=="],
|
||||
|
||||
"@parcel/watcher-linux-arm64-musl": ["@parcel/watcher-linux-arm64-musl@2.5.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg=="],
|
||||
|
||||
"@parcel/watcher-linux-x64-glibc": ["@parcel/watcher-linux-x64-glibc@2.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A=="],
|
||||
|
||||
"@parcel/watcher-linux-x64-musl": ["@parcel/watcher-linux-x64-musl@2.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg=="],
|
||||
|
||||
"@parcel/watcher-win32-arm64": ["@parcel/watcher-win32-arm64@2.5.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw=="],
|
||||
|
||||
"@parcel/watcher-win32-ia32": ["@parcel/watcher-win32-ia32@2.5.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ=="],
|
||||
|
||||
"@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="],
|
||||
|
||||
"@popperjs/core": ["@popperjs/core@2.11.8", "", {}, "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="],
|
||||
|
||||
"@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="],
|
||||
|
||||
"@rushstack/eslint-patch": ["@rushstack/eslint-patch@1.11.0", "", {}, "sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ=="],
|
||||
|
||||
"@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="],
|
||||
|
||||
"@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
|
||||
|
||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="],
|
||||
|
||||
"@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="],
|
||||
|
||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||
|
||||
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
|
||||
|
||||
"@types/node": ["@types/node@20.17.30", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-7zf4YyHA+jvBNfVrk2Gtvs6x7E8V+YDW05bNfG2XkWDJfYRXrTiP/DsB2zSYTaHX0bGIujTBQdMVAhb+j7mwpg=="],
|
||||
|
||||
"@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="],
|
||||
|
||||
"@types/prop-types": ["@types/prop-types@15.7.14", "", {}, "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ=="],
|
||||
|
||||
"@types/react": ["@types/react@19.1.0", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-UaicktuQI+9UKyA4njtDOGBD/67t8YEBt2xdfqu8+gP9hqPUPsiXlNPcpS2gVdjmis5GKPG3fCxbQLVgxsQZ8w=="],
|
||||
|
||||
"@types/react-dom": ["@types/react-dom@19.1.1", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-jFf/woGTVTjUJsl2O7hcopJ1r0upqoq/vIOoCj0yLh3RIXxWcljlpuZ+vEBRXsymD1jhfeJrlyTy/S1UW+4y1w=="],
|
||||
|
||||
"@types/react-transition-group": ["@types/react-transition-group@4.4.12", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.29.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.29.0", "@typescript-eslint/type-utils": "8.29.0", "@typescript-eslint/utils": "8.29.0", "@typescript-eslint/visitor-keys": "8.29.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.29.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.29.0", "@typescript-eslint/types": "8.29.0", "@typescript-eslint/typescript-estree": "8.29.0", "@typescript-eslint/visitor-keys": "8.29.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g=="],
|
||||
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.29.0", "", { "dependencies": { "@typescript-eslint/types": "8.29.0", "@typescript-eslint/visitor-keys": "8.29.0" } }, "sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw=="],
|
||||
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.29.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.29.0", "@typescript-eslint/utils": "8.29.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q=="],
|
||||
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.29.0", "", {}, "sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.29.0", "", { "dependencies": { "@typescript-eslint/types": "8.29.0", "@typescript-eslint/visitor-keys": "8.29.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow=="],
|
||||
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.29.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.29.0", "@typescript-eslint/types": "8.29.0", "@typescript-eslint/typescript-estree": "8.29.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA=="],
|
||||
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.29.0", "", { "dependencies": { "@typescript-eslint/types": "8.29.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg=="],
|
||||
|
||||
"@unrs/resolver-binding-darwin-arm64": ["@unrs/resolver-binding-darwin-arm64@1.3.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-EpRILdWr3/xDa/7MoyfO7JuBIJqpBMphtu4+80BK1bRfFcniVT74h3Z7q1+WOc92FuIAYatB1vn9TJR67sORGw=="],
|
||||
|
||||
"@unrs/resolver-binding-darwin-x64": ["@unrs/resolver-binding-darwin-x64@1.3.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-ntj/g7lPyqwinMJWZ+DKHBse8HhVxswGTmNgFKJtdgGub3M3zp5BSZ3bvMP+kBT6dnYJLSVlDqdwOq1P8i0+/g=="],
|
||||
|
||||
"@unrs/resolver-binding-freebsd-x64": ["@unrs/resolver-binding-freebsd-x64@1.3.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-l6BT8f2CU821EW7U8hSUK8XPq4bmyTlt9Mn4ERrfjJNoCw0/JoHAh9amZZtV3cwC3bwwIat+GUnrcHTG9+qixw=="],
|
||||
|
||||
"@unrs/resolver-binding-linux-arm-gnueabihf": ["@unrs/resolver-binding-linux-arm-gnueabihf@1.3.3", "", { "os": "linux", "cpu": "arm" }, "sha512-8ScEc5a4y7oE2BonRvzJ+2GSkBaYWyh0/Ko4Q25e/ix6ANpJNhwEPZvCR6GVRmsQAYMIfQvYLdM6YEN+qRjnAQ=="],
|
||||
|
||||
"@unrs/resolver-binding-linux-arm-musleabihf": ["@unrs/resolver-binding-linux-arm-musleabihf@1.3.3", "", { "os": "linux", "cpu": "arm" }, "sha512-8qQ6l1VTzLNd3xb2IEXISOKwMGXDCzY/UNy/7SovFW2Sp0K3YbL7Ao7R18v6SQkLqQlhhqSBIFRk+u6+qu5R5A=="],
|
||||
|
||||
"@unrs/resolver-binding-linux-arm64-gnu": ["@unrs/resolver-binding-linux-arm64-gnu@1.3.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-v81R2wjqcWXJlQY23byqYHt9221h4anQ6wwN64oMD/WAE+FmxPHFZee5bhRkNVtzqO/q7wki33VFWlhiADwUeQ=="],
|
||||
|
||||
"@unrs/resolver-binding-linux-arm64-musl": ["@unrs/resolver-binding-linux-arm64-musl@1.3.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-cAOx/j0u5coMg4oct/BwMzvWJdVciVauUvsd+GQB/1FZYKQZmqPy0EjJzJGbVzFc6gbnfEcSqvQE6gvbGf2N8Q=="],
|
||||
|
||||
"@unrs/resolver-binding-linux-ppc64-gnu": ["@unrs/resolver-binding-linux-ppc64-gnu@1.3.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-mq2blqwErgDJD4gtFDlTX/HZ7lNP8YCHYFij2gkXPtMzrXxPW1hOtxL6xg4NWxvnj4bppppb0W3s/buvM55yfg=="],
|
||||
|
||||
"@unrs/resolver-binding-linux-s390x-gnu": ["@unrs/resolver-binding-linux-s390x-gnu@1.3.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-u0VRzfFYysarYHnztj2k2xr+eu9rmgoTUUgCCIT37Nr+j0A05Xk2c3RY8Mh5+DhCl2aYibihnaAEJHeR0UOFIQ=="],
|
||||
|
||||
"@unrs/resolver-binding-linux-x64-gnu": ["@unrs/resolver-binding-linux-x64-gnu@1.3.3", "", { "os": "linux", "cpu": "x64" }, "sha512-OrVo5ZsG29kBF0Ug95a2KidS16PqAMmQNozM6InbquOfW/udouk063e25JVLqIBhHLB2WyBnixOQ19tmeC/hIg=="],
|
||||
|
||||
"@unrs/resolver-binding-linux-x64-musl": ["@unrs/resolver-binding-linux-x64-musl@1.3.3", "", { "os": "linux", "cpu": "x64" }, "sha512-PYnmrwZ4HMp9SkrOhqPghY/aoL+Rtd4CQbr93GlrRTjK6kDzfMfgz3UH3jt6elrQAfupa1qyr1uXzeVmoEAxUA=="],
|
||||
|
||||
"@unrs/resolver-binding-wasm32-wasi": ["@unrs/resolver-binding-wasm32-wasi@1.3.3", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.7" }, "cpu": "none" }, "sha512-81AnQY6fShmktQw4hWDUIilsKSdvr/acdJ5azAreu2IWNlaJOKphJSsUVWE+yCk6kBMoQyG9ZHCb/krb5K0PEA=="],
|
||||
|
||||
"@unrs/resolver-binding-win32-arm64-msvc": ["@unrs/resolver-binding-win32-arm64-msvc@1.3.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-X/42BMNw7cW6xrB9syuP5RusRnWGoq+IqvJO8IDpp/BZg64J1uuIW6qA/1Cl13Y4LyLXbJVYbYNSKwR/FiHEng=="],
|
||||
|
||||
"@unrs/resolver-binding-win32-ia32-msvc": ["@unrs/resolver-binding-win32-ia32-msvc@1.3.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-EGNnNGQxMU5aTN7js3ETYvuw882zcO+dsVjs+DwO2j/fRVKth87C8e2GzxW1L3+iWAXMyJhvFBKRavk9Og1Z6A=="],
|
||||
|
||||
"@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.3.3", "", { "os": "win32", "cpu": "x64" }, "sha512-GraLbYqOJcmW1qY3osB+2YIiD62nVf2/bVLHZmrb4t/YSUwE03l7TwcDJl08T/Tm3SVhepX8RQkpzWbag/Sb4w=="],
|
||||
|
||||
"acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="],
|
||||
|
||||
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
|
||||
|
||||
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||
|
||||
"aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
|
||||
|
||||
"array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="],
|
||||
|
||||
"array-includes": ["array-includes@3.1.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" } }, "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ=="],
|
||||
|
||||
"array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="],
|
||||
|
||||
"array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.6", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-shim-unscopables": "^1.1.0" } }, "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ=="],
|
||||
|
||||
"array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="],
|
||||
|
||||
"array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="],
|
||||
|
||||
"array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="],
|
||||
|
||||
"arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="],
|
||||
|
||||
"ast-types-flow": ["ast-types-flow@0.0.8", "", {}, "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ=="],
|
||||
|
||||
"async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
|
||||
|
||||
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
|
||||
|
||||
"axe-core": ["axe-core@4.10.3", "", {}, "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg=="],
|
||||
|
||||
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
|
||||
|
||||
"babel-plugin-macros": ["babel-plugin-macros@3.1.0", "", { "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", "resolve": "^1.19.0" } }, "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg=="],
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
||||
|
||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||
|
||||
"busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="],
|
||||
|
||||
"call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
|
||||
|
||||
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||
|
||||
"call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
|
||||
|
||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001709", "", {}, "sha512-NgL3vUTnDrPCZ3zTahp4fsugQ4dc7EKTSzwQDPEel6DMoMnfH2jhry9n2Zm8onbSR+f/QtKHFOA+iAQu4kbtWA=="],
|
||||
|
||||
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||
|
||||
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
||||
|
||||
"client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
|
||||
|
||||
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
|
||||
|
||||
"color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
|
||||
|
||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||
|
||||
"convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="],
|
||||
|
||||
"cosmiconfig": ["cosmiconfig@7.1.0", "", { "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" } }, "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||
|
||||
"damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="],
|
||||
|
||||
"data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="],
|
||||
|
||||
"data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="],
|
||||
|
||||
"data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
|
||||
|
||||
"debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="],
|
||||
|
||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||
|
||||
"define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
|
||||
|
||||
"define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="],
|
||||
|
||||
"doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
|
||||
|
||||
"dom-helpers": ["dom-helpers@5.2.1", "", { "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" } }, "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA=="],
|
||||
|
||||
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
|
||||
"error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="],
|
||||
|
||||
"es-abstract": ["es-abstract@1.23.9", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.3", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.0", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-regex": "^1.2.1", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.0", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.3", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.3", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.18" } }, "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA=="],
|
||||
|
||||
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||
|
||||
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||
|
||||
"es-iterator-helpers": ["es-iterator-helpers@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.6", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.4", "safe-array-concat": "^1.1.3" } }, "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w=="],
|
||||
|
||||
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
||||
|
||||
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
|
||||
|
||||
"es-shim-unscopables": ["es-shim-unscopables@1.1.0", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw=="],
|
||||
|
||||
"es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="],
|
||||
|
||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||
|
||||
"eslint": ["eslint@9.23.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.2", "@eslint/config-helpers": "^0.2.0", "@eslint/core": "^0.12.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.23.0", "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw=="],
|
||||
|
||||
"eslint-config-next": ["eslint-config-next@15.1.0", "", { "dependencies": { "@next/eslint-plugin-next": "15.1.0", "@rushstack/eslint-patch": "^1.10.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^5.0.0" }, "peerDependencies": { "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", "typescript": ">=3.3.1" }, "optionalPeers": ["typescript"] }, "sha512-gADO+nKVseGso3DtOrYX9H7TxB/MuX7AUYhMlvQMqLYvUWu4HrOQuU7cC1HW74tHIqkAvXdwgAz3TCbczzSEXw=="],
|
||||
|
||||
"eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="],
|
||||
|
||||
"eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.0", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.12", "unrs-resolver": "^1.3.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import", "eslint-plugin-import-x"] }, "sha512-aV3/dVsT0/H9BtpNwbaqvl+0xGMRGzncLyhm793NFGvbwGGvzyAykqWZ8oZlZuGwuHkwJjhWJkG1cM3ynvd2pQ=="],
|
||||
|
||||
"eslint-module-utils": ["eslint-module-utils@2.12.0", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg=="],
|
||||
|
||||
"eslint-plugin-import": ["eslint-plugin-import@2.31.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.8", "array.prototype.findlastindex": "^1.2.5", "array.prototype.flat": "^1.3.2", "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.0", "hasown": "^2.0.2", "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.0", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.8", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A=="],
|
||||
|
||||
"eslint-plugin-jsx-a11y": ["eslint-plugin-jsx-a11y@6.10.2", "", { "dependencies": { "aria-query": "^5.3.2", "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", "axe-core": "^4.10.0", "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "safe-regex-test": "^1.0.3", "string.prototype.includes": "^2.0.1" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q=="],
|
||||
|
||||
"eslint-plugin-react": ["eslint-plugin-react@7.37.4", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.8", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ=="],
|
||||
|
||||
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
|
||||
|
||||
"eslint-scope": ["eslint-scope@8.3.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ=="],
|
||||
|
||||
"eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="],
|
||||
|
||||
"espree": ["espree@10.3.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" } }, "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg=="],
|
||||
|
||||
"esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="],
|
||||
|
||||
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
|
||||
|
||||
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
|
||||
|
||||
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
|
||||
|
||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||
|
||||
"fast-glob": ["fast-glob@3.3.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg=="],
|
||||
|
||||
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
|
||||
|
||||
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
|
||||
|
||||
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
|
||||
|
||||
"fdir": ["fdir@6.4.3", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw=="],
|
||||
|
||||
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
|
||||
|
||||
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
|
||||
|
||||
"find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="],
|
||||
|
||||
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
|
||||
|
||||
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
|
||||
|
||||
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
|
||||
|
||||
"for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
|
||||
|
||||
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||
|
||||
"function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="],
|
||||
|
||||
"functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="],
|
||||
|
||||
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
||||
|
||||
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||
|
||||
"get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="],
|
||||
|
||||
"get-tsconfig": ["get-tsconfig@4.10.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A=="],
|
||||
|
||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||
|
||||
"globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
|
||||
|
||||
"globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
|
||||
|
||||
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||
|
||||
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
|
||||
|
||||
"has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
|
||||
|
||||
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||
|
||||
"has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="],
|
||||
|
||||
"has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="],
|
||||
|
||||
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
||||
|
||||
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
|
||||
|
||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||
|
||||
"hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="],
|
||||
|
||||
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||
|
||||
"immutable": ["immutable@5.1.1", "", {}, "sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg=="],
|
||||
|
||||
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||
|
||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||
|
||||
"internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
|
||||
|
||||
"is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="],
|
||||
|
||||
"is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
|
||||
|
||||
"is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="],
|
||||
|
||||
"is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="],
|
||||
|
||||
"is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="],
|
||||
|
||||
"is-bun-module": ["is-bun-module@2.0.0", "", { "dependencies": { "semver": "^7.7.1" } }, "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ=="],
|
||||
|
||||
"is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
|
||||
|
||||
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
|
||||
|
||||
"is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="],
|
||||
|
||||
"is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="],
|
||||
|
||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||
|
||||
"is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="],
|
||||
|
||||
"is-generator-function": ["is-generator-function@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "get-proto": "^1.0.0", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ=="],
|
||||
|
||||
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||
|
||||
"is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="],
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
"is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="],
|
||||
|
||||
"is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="],
|
||||
|
||||
"is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="],
|
||||
|
||||
"is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="],
|
||||
|
||||
"is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="],
|
||||
|
||||
"is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="],
|
||||
|
||||
"is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="],
|
||||
|
||||
"is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="],
|
||||
|
||||
"is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="],
|
||||
|
||||
"is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="],
|
||||
|
||||
"isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="],
|
||||
|
||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
|
||||
|
||||
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
|
||||
|
||||
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
|
||||
|
||||
"json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
|
||||
|
||||
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
||||
|
||||
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
|
||||
|
||||
"json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="],
|
||||
|
||||
"jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="],
|
||||
|
||||
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
|
||||
|
||||
"language-subtag-registry": ["language-subtag-registry@0.3.23", "", {}, "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ=="],
|
||||
|
||||
"language-tags": ["language-tags@1.0.9", "", { "dependencies": { "language-subtag-registry": "^0.3.20" } }, "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA=="],
|
||||
|
||||
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
||||
|
||||
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
||||
|
||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||
|
||||
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
||||
|
||||
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
|
||||
|
||||
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||
|
||||
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
||||
|
||||
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||
|
||||
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
|
||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||
|
||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||
|
||||
"next": ["next@15.2.4", "", { "dependencies": { "@next/env": "15.2.4", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.2.4", "@next/swc-darwin-x64": "15.2.4", "@next/swc-linux-arm64-gnu": "15.2.4", "@next/swc-linux-arm64-musl": "15.2.4", "@next/swc-linux-x64-gnu": "15.2.4", "@next/swc-linux-x64-musl": "15.2.4", "@next/swc-win32-arm64-msvc": "15.2.4", "@next/swc-win32-x64-msvc": "15.2.4", "sharp": "^0.33.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-VwL+LAaPSxEkd3lU2xWbgEOtrM8oedmyhBqaVNmgKB+GvZlCy9rgaEc+y2on0wv+l0oSFqLtYD6dcC1eAedUaQ=="],
|
||||
|
||||
"node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
|
||||
|
||||
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||
|
||||
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
|
||||
|
||||
"object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
|
||||
|
||||
"object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="],
|
||||
|
||||
"object.entries": ["object.entries@1.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.1" } }, "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw=="],
|
||||
|
||||
"object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="],
|
||||
|
||||
"object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="],
|
||||
|
||||
"object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="],
|
||||
|
||||
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
|
||||
|
||||
"own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="],
|
||||
|
||||
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
|
||||
|
||||
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
|
||||
|
||||
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
||||
|
||||
"parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="],
|
||||
|
||||
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
||||
|
||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
|
||||
|
||||
"path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],
|
||||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
|
||||
"picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
||||
|
||||
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
|
||||
|
||||
"postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
|
||||
|
||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||
|
||||
"prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||
|
||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||
|
||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||
|
||||
"react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="],
|
||||
|
||||
"react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="],
|
||||
|
||||
"react-is": ["react-is@19.1.0", "", {}, "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg=="],
|
||||
|
||||
"react-transition-group": ["react-transition-group@4.4.5", "", { "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", "loose-envify": "^1.4.0", "prop-types": "^15.6.2" }, "peerDependencies": { "react": ">=16.6.0", "react-dom": ">=16.6.0" } }, "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g=="],
|
||||
|
||||
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
|
||||
|
||||
"reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="],
|
||||
|
||||
"regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="],
|
||||
|
||||
"regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
|
||||
|
||||
"resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="],
|
||||
|
||||
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||
|
||||
"resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
|
||||
|
||||
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
|
||||
|
||||
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||
|
||||
"safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="],
|
||||
|
||||
"safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="],
|
||||
|
||||
"safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
|
||||
|
||||
"sass": ["sass@1.86.2", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-Rpfn0zAIDqvnSb2DihJTDFjbhqLHu91Wqac9rxontWk7R+2txcPjuujMqu1eeoezh5kAblVCS5EdFdyr0Jmu+w=="],
|
||||
|
||||
"scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
|
||||
|
||||
"semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
|
||||
"set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="],
|
||||
|
||||
"set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="],
|
||||
|
||||
"set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="],
|
||||
|
||||
"sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
|
||||
|
||||
"side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
|
||||
|
||||
"side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
|
||||
|
||||
"side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
|
||||
|
||||
"simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="],
|
||||
|
||||
"source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="],
|
||||
|
||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||
|
||||
"stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="],
|
||||
|
||||
"streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="],
|
||||
|
||||
"string.prototype.includes": ["string.prototype.includes@2.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3" } }, "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg=="],
|
||||
|
||||
"string.prototype.matchall": ["string.prototype.matchall@4.0.12", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="],
|
||||
|
||||
"string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="],
|
||||
|
||||
"string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="],
|
||||
|
||||
"string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="],
|
||||
|
||||
"string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="],
|
||||
|
||||
"strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
|
||||
|
||||
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
||||
|
||||
"styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="],
|
||||
|
||||
"stylis": ["stylis@4.2.0", "", {}, "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="],
|
||||
|
||||
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||
|
||||
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.12", "", { "dependencies": { "fdir": "^6.4.3", "picomatch": "^4.0.2" } }, "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww=="],
|
||||
|
||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||
|
||||
"ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="],
|
||||
|
||||
"tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
|
||||
|
||||
"typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="],
|
||||
|
||||
"typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="],
|
||||
|
||||
"typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="],
|
||||
|
||||
"typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
|
||||
|
||||
"typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="],
|
||||
|
||||
"unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
|
||||
|
||||
"undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="],
|
||||
|
||||
"unrs-resolver": ["unrs-resolver@1.3.3", "", { "optionalDependencies": { "@unrs/resolver-binding-darwin-arm64": "1.3.3", "@unrs/resolver-binding-darwin-x64": "1.3.3", "@unrs/resolver-binding-freebsd-x64": "1.3.3", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.3.3", "@unrs/resolver-binding-linux-arm-musleabihf": "1.3.3", "@unrs/resolver-binding-linux-arm64-gnu": "1.3.3", "@unrs/resolver-binding-linux-arm64-musl": "1.3.3", "@unrs/resolver-binding-linux-ppc64-gnu": "1.3.3", "@unrs/resolver-binding-linux-s390x-gnu": "1.3.3", "@unrs/resolver-binding-linux-x64-gnu": "1.3.3", "@unrs/resolver-binding-linux-x64-musl": "1.3.3", "@unrs/resolver-binding-wasm32-wasi": "1.3.3", "@unrs/resolver-binding-win32-arm64-msvc": "1.3.3", "@unrs/resolver-binding-win32-ia32-msvc": "1.3.3", "@unrs/resolver-binding-win32-x64-msvc": "1.3.3" } }, "sha512-PFLAGQzYlyjniXdbmQ3dnGMZJXX5yrl2YS4DLRfR3BhgUsE1zpRIrccp9XMOGRfIHpdFvCn/nr5N1KMVda4x3A=="],
|
||||
|
||||
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
|
||||
|
||||
"which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="],
|
||||
|
||||
"which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="],
|
||||
|
||||
"which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="],
|
||||
|
||||
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
||||
|
||||
"yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="],
|
||||
|
||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||
|
||||
"@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
|
||||
|
||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||
|
||||
"@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.13.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw=="],
|
||||
|
||||
"@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="],
|
||||
|
||||
"@parcel/watcher/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
|
||||
"error-ex/is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
|
||||
|
||||
"eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||
|
||||
"eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||
|
||||
"eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||
|
||||
"eslint-plugin-react/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="],
|
||||
|
||||
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"hoist-non-react-statics/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||
|
||||
"is-bun-module/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
|
||||
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||
|
||||
"sharp/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,11 @@ const nextConfig: NextConfig = {
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: 'https',
|
||||
hostname: 'api.ic3.space',
|
||||
pathname: '/strafe/map-images/**',
|
||||
port: '',
|
||||
search: '',
|
||||
protocol: "https",
|
||||
hostname: "tr.rbxcdn.com",
|
||||
pathname: "/**",
|
||||
port: "",
|
||||
search: "",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -19,13 +19,12 @@ export default function Header() {
|
||||
<header className="header-bar">
|
||||
<nav className="left">
|
||||
<HeaderButton name="Submissions" href="/submissions"/>
|
||||
<HeaderButton name="Mapfixes" href="/mapfixes"/>
|
||||
<HeaderButton name="Maps" href="/maps"/>
|
||||
</nav>
|
||||
<nav className="right">
|
||||
<HeaderButton name="Submit" href="/submit"/>
|
||||
<HeaderButton name="Need" href=""/>
|
||||
<HeaderButton name="Menu" href=""/>
|
||||
<HeaderButton name="Items" href=""/>
|
||||
</nav>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
71
web/src/app/_components/mapCard.tsx
Normal file
71
web/src/app/_components/mapCard.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { Rating } from "@mui/material";
|
||||
|
||||
interface SubmissionCardProps {
|
||||
displayName: string;
|
||||
assetId: number;
|
||||
authorId: number;
|
||||
author: string;
|
||||
rating: number;
|
||||
id: number;
|
||||
}
|
||||
|
||||
export function SubmissionCard(props: SubmissionCardProps) {
|
||||
return (
|
||||
<Link href={`/submissions/${props.id}`}>
|
||||
<div className="submissionCard">
|
||||
<div className="content">
|
||||
<div className="map-image">
|
||||
{/* TODO: Grab image of model */}
|
||||
<Image width={230} height={230} layout="fixed" priority={true} src={`/thumbnails/asset/${props.assetId}`} alt={props.displayName} />
|
||||
</div>
|
||||
<div className="details">
|
||||
<div className="header">
|
||||
<span className="displayName">{props.displayName}</span>
|
||||
<div className="rating">
|
||||
<Rating value={props.rating} readOnly size="small" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer">
|
||||
<div className="author">
|
||||
<Image className="avatar" width={28} height={28} priority={true} src={`/thumbnails/user/${props.authorId}`} alt={props.author}/>
|
||||
<span>{props.author}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export function MapfixCard(props: SubmissionCardProps) {
|
||||
return (
|
||||
<Link href={`/mapfixes/${props.id}`}>
|
||||
<div className="MapfixCard">
|
||||
<div className="content">
|
||||
<div className="map-image">
|
||||
{/* TODO: Grab image of model */}
|
||||
<Image width={230} height={230} layout="fixed" priority={true} src={`/thumbnails/asset/${props.assetId}`} alt={props.displayName} />
|
||||
</div>
|
||||
<div className="details">
|
||||
<div className="header">
|
||||
<span className="displayName">{props.displayName}</span>
|
||||
<div className="rating">
|
||||
<Rating value={props.rating} readOnly size="small" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer">
|
||||
<div className="author">
|
||||
<Image className="avatar" width={28} height={28} priority={true} src={`/thumbnails/user/${props.authorId}`} alt={props.author}/>
|
||||
<span>{props.author}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@use "../../../globals.scss";
|
||||
@use "../../globals.scss";
|
||||
|
||||
.submissionCard {
|
||||
display: flex;
|
||||
@@ -9,7 +9,7 @@
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
min-width: 180px;
|
||||
min-width: 230px;
|
||||
max-width: 340px;
|
||||
}
|
||||
|
||||
@@ -43,8 +43,6 @@
|
||||
overflow: hidden;
|
||||
|
||||
> img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
75
web/src/app/mapfixes/(styles)/page.scss
Normal file
75
web/src/app/mapfixes/(styles)/page.scss
Normal file
@@ -0,0 +1,75 @@
|
||||
@forward "../../_components/styles/mapCard.scss";
|
||||
|
||||
@use "../../globals.scss";
|
||||
|
||||
a {
|
||||
color:rgb(255, 255, 255);
|
||||
|
||||
&:visited, &:hover, &:focus {
|
||||
text-decoration: none;
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
&:active {
|
||||
color: rgb(192, 192, 192)
|
||||
}
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
grid-template-rows: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
overflow-x: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin: 0.3rem;
|
||||
}
|
||||
|
||||
.pagination button {
|
||||
padding: 0.25rem 0.5rem;
|
||||
font-size: 1.15rem;
|
||||
border: none;
|
||||
border-radius: 0.35rem;
|
||||
background-color: #33333350;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pagination button:disabled {
|
||||
background-color: #5555559a;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.pagination-dots {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.35rem;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background-color: #bbb;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dot.active {
|
||||
background-color: #333;
|
||||
}
|
||||
19
web/src/app/mapfixes/[mapfixId]/(styles)/page.scss
Normal file
19
web/src/app/mapfixes/[mapfixId]/(styles)/page.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
@forward "./page/commentWindow.scss";
|
||||
@forward "./page/reviewStatus.scss";
|
||||
@forward "./page/ratingWindow.scss";
|
||||
@forward "./page/reviewButtons.scss";
|
||||
@forward "./page/comments.scss";
|
||||
@forward "./page/review.scss";
|
||||
@forward "./page/map.scss";
|
||||
|
||||
@use "../../../globals.scss";
|
||||
|
||||
.map-page-main {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.by-creator {
|
||||
margin-top: 10px;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
@use "../../../../globals.scss";
|
||||
|
||||
#comment-text-field {
|
||||
@include globals.border-with-radius;
|
||||
resize: none;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
background-color: var(--comment-area)
|
||||
}
|
||||
|
||||
.leave-comment-window {
|
||||
@include globals.border-with-radius;
|
||||
width: 100%;
|
||||
height: 230px;
|
||||
margin-top: 35px;
|
||||
|
||||
.rating-type {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
gap: 35%;
|
||||
|
||||
.rating-right {
|
||||
display: grid;
|
||||
|
||||
> span {
|
||||
margin: 6px 0 6px 0;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 15px 0 15px 0;
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: var(--window-header);
|
||||
border-bottom: globals.$review-border;
|
||||
height: 45px;
|
||||
|
||||
p {
|
||||
font-weight: bold;
|
||||
margin: 0 0 0 20px;
|
||||
}
|
||||
}
|
||||
main {
|
||||
padding: 20px;
|
||||
|
||||
button {
|
||||
margin-top: 9px;
|
||||
}
|
||||
}
|
||||
}
|
||||
49
web/src/app/mapfixes/[mapfixId]/(styles)/page/comments.scss
Normal file
49
web/src/app/mapfixes/[mapfixId]/(styles)/page/comments.scss
Normal file
@@ -0,0 +1,49 @@
|
||||
$comments-size: 60px;
|
||||
|
||||
.comments {
|
||||
display: grid;
|
||||
gap: 25px;
|
||||
margin-top: 20px;
|
||||
|
||||
.no-comments {
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.commenter {
|
||||
display: flex;
|
||||
height: $comments-size;
|
||||
|
||||
//BhopMaptest comment
|
||||
&[data-highlighted="true"] {
|
||||
background-color: var(--comment-highlighted);
|
||||
}
|
||||
> img {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.name {
|
||||
font: {
|
||||
weight: 500;
|
||||
size: 1.3em;
|
||||
};
|
||||
}
|
||||
.date {
|
||||
font-size: .8em;
|
||||
margin: 0 0 0 5px;
|
||||
color: #646464
|
||||
}
|
||||
.details {
|
||||
display: grid;
|
||||
margin-left: 10px;
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
p:not(.date) {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
web/src/app/mapfixes/[mapfixId]/(styles)/page/map.scss
Normal file
15
web/src/app/mapfixes/[mapfixId]/(styles)/page/map.scss
Normal file
@@ -0,0 +1,15 @@
|
||||
@use "../../../../globals.scss";
|
||||
|
||||
.map-image-area {
|
||||
@include globals.border-with-radius;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
|
||||
> p {
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
@use "../../../../globals.scss";
|
||||
|
||||
.rating-window {
|
||||
@include globals.border-with-radius;
|
||||
width: 100%;
|
||||
|
||||
.rating-type {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
gap: 35%;
|
||||
|
||||
.rating-right {
|
||||
display: grid;
|
||||
|
||||
> span {
|
||||
margin: 6px 0 6px 0;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 15px 0 15px 0;
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: var(--window-header);
|
||||
border-bottom: globals.$review-border;
|
||||
height: 45px;
|
||||
|
||||
p {
|
||||
font-weight: bold;
|
||||
margin: 0 0 0 20px;
|
||||
}
|
||||
}
|
||||
main {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
}
|
||||
47
web/src/app/mapfixes/[mapfixId]/(styles)/page/review.scss
Normal file
47
web/src/app/mapfixes/[mapfixId]/(styles)/page/review.scss
Normal file
@@ -0,0 +1,47 @@
|
||||
@use "../../../../globals.scss";
|
||||
|
||||
.review-info {
|
||||
width: 650px;
|
||||
height: 100%;
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
p, h1 {
|
||||
color: var(--text-color);
|
||||
}
|
||||
h1 {
|
||||
font: {
|
||||
weight: 500;
|
||||
size: 1.8rem
|
||||
};
|
||||
margin: 0;
|
||||
}
|
||||
a {
|
||||
color: var(--anchor-link-review);
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.review-section {
|
||||
display: flex;
|
||||
gap: 50px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.review-area {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
gap: 25px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
object-fit: contain
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
@use "../../../../globals.scss";
|
||||
|
||||
.review-set {
|
||||
@include globals.border-with-radius;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
$UnderConstruction: "0";
|
||||
$Submitted: "1";
|
||||
$ChangesRequested: "2";
|
||||
$Accepted: "3";
|
||||
$Validating: "4";
|
||||
$Validated: "5";
|
||||
$Uploading: "6";
|
||||
$Uploaded: "7";
|
||||
$Rejected: "8";
|
||||
$Released: "9";
|
||||
|
||||
.review-status {
|
||||
border-radius: 5px;
|
||||
|
||||
p {
|
||||
margin: 3px 25px 3px 25px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&[data-review-status="#{$Released}"] {
|
||||
background-color: orange;
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
&[data-review-status="#{$Rejected}"] {
|
||||
background-color: orange;
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
&[data-review-status="#{$Uploading}"] {
|
||||
background-color: orange;
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
&[data-review-status="#{$Uploaded}"] {
|
||||
background-color: orange;
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
&[data-review-status="#{$Validated}"] {
|
||||
background-color: orange;
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
&[data-review-status="#{$Validating}"] {
|
||||
background-color: orange;
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
&[data-review-status="#{$Accepted}"] {
|
||||
background-color: rgb(2, 162, 2);
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
&[data-review-status="#{$ChangesRequested}"] {
|
||||
background-color: orange;
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
&[data-review-status="#{$Submitted}"] {
|
||||
background-color: orange;
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
&[data-review-status="#{$UnderConstruction}"] {
|
||||
background-color: orange;
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
web/src/app/mapfixes/[mapfixId]/_comments.tsx
Normal file
70
web/src/app/mapfixes/[mapfixId]/_comments.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import type { MapfixInfo } from "@/app/ts/Mapfix";
|
||||
import { Button } from "@mui/material"
|
||||
import Window from "./_window";
|
||||
import SendIcon from '@mui/icons-material/Send';
|
||||
import Image from "next/image";
|
||||
|
||||
interface CommentersProps {
|
||||
comments_data: CreatorAndReviewStatus
|
||||
}
|
||||
|
||||
interface CreatorAndReviewStatus {
|
||||
asset_id: MapfixInfo["AssetID"],
|
||||
creator: MapfixInfo["DisplayName"],
|
||||
review: MapfixInfo["StatusID"],
|
||||
status_message: MapfixInfo["StatusMessage"],
|
||||
submitter: MapfixInfo["Submitter"],
|
||||
target_asset_id: MapfixInfo["TargetAssetID"],
|
||||
comments: Comment[],
|
||||
name: string
|
||||
}
|
||||
|
||||
interface Comment {
|
||||
picture?: string, //TEMP
|
||||
comment: string,
|
||||
date: string,
|
||||
name: string
|
||||
}
|
||||
|
||||
function AddComment(comment: Comment) {
|
||||
const IsBhopMaptest = comment.name == "BhopMaptest" //Highlighted commenter
|
||||
|
||||
return (
|
||||
<div className="commenter" data-highlighted={IsBhopMaptest}>
|
||||
<Image src={comment.picture as string} alt={`${comment.name}'s comment`}/>
|
||||
<div className="details">
|
||||
<header>
|
||||
<p className="name">{comment.name}</p>
|
||||
<p className="date">{comment.date}</p>
|
||||
</header>
|
||||
<p className="comment">{comment.comment}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function LeaveAComment() {
|
||||
return (
|
||||
<Window title="Leave a Comment:" className="leave-comment-window">
|
||||
<textarea name="comment-box" id="comment-text-field"></textarea>
|
||||
<Button variant="outlined" endIcon={<SendIcon/>}>Submit</Button>
|
||||
</Window>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Comments(stats: CommentersProps) {
|
||||
return (<>
|
||||
<section className="comments">
|
||||
{stats.comments_data.comments.length===0
|
||||
&& <p className="no-comments">There are no comments.</p>
|
||||
|| stats.comments_data.comments.map(comment => (
|
||||
<AddComment key={comment.name} name={comment.name} date={comment.date} comment={comment.comment}/>
|
||||
))}
|
||||
</section>
|
||||
<LeaveAComment/>
|
||||
</>)
|
||||
}
|
||||
|
||||
export {
|
||||
type CreatorAndReviewStatus
|
||||
}
|
||||
31
web/src/app/mapfixes/[mapfixId]/_mapImage.tsx
Normal file
31
web/src/app/mapfixes/[mapfixId]/_mapImage.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import Image from "next/image";
|
||||
import { MapfixInfo } from "@/app/ts/Mapfix"
|
||||
|
||||
interface AssetID {
|
||||
id: MapfixInfo["AssetID"]
|
||||
}
|
||||
|
||||
function MapImage({ id }: AssetID) {
|
||||
if (!id) {
|
||||
return <p>Missing asset ID</p>;
|
||||
}
|
||||
|
||||
const imageUrl = `/thumbnails/asset/${id}`;
|
||||
|
||||
return (
|
||||
<Image
|
||||
src={imageUrl}
|
||||
alt="Map Thumbnail"
|
||||
layout="responsive"
|
||||
width={512}
|
||||
height={512}
|
||||
priority={true}
|
||||
className="map-image"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
type AssetID,
|
||||
MapImage
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user