Add new Swagger Doc for the pusher
This commit is contained in:
parent
231facbae2
commit
53b084ea7f
@ -40,6 +40,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/thecodingmachine/workadventure#readme",
|
"homepage": "https://github.com/thecodingmachine/workadventure#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@anatine/zod-openapi": "^1.3.0",
|
||||||
"@workadventure/tiled-map-type-guard": "^1.0.3",
|
"@workadventure/tiled-map-type-guard": "^1.0.3",
|
||||||
"axios": "^0.21.2",
|
"axios": "^0.21.2",
|
||||||
"busboy": "^0.3.1",
|
"busboy": "^0.3.1",
|
||||||
@ -50,6 +51,7 @@
|
|||||||
"ipaddr.js": "^2.0.1",
|
"ipaddr.js": "^2.0.1",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"mkdirp": "^1.0.4",
|
"mkdirp": "^1.0.4",
|
||||||
|
"openapi3-ts": "^2.0.2",
|
||||||
"prom-client": "^12.0.0",
|
"prom-client": "^12.0.0",
|
||||||
"query-string": "^6.13.3",
|
"query-string": "^6.13.3",
|
||||||
"redis": "^3.1.2",
|
"redis": "^3.1.2",
|
||||||
|
@ -2,6 +2,14 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@anatine/zod-openapi@^1.3.0":
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@anatine/zod-openapi/-/zod-openapi-1.3.0.tgz#b5b38c3d821b79674226aa7b327c88c371860d0d"
|
||||||
|
integrity sha512-l54DypUdDsIq1Uwjv4ib9IBkTXMKZQLUj7qvdFL51EExC5LdSSqOlTOyaVVZZGYgWPKM7ZjGklhdoknLz4EC+w==
|
||||||
|
dependencies:
|
||||||
|
ts-deepmerge "^1.1.0"
|
||||||
|
validator "^13.7.0"
|
||||||
|
|
||||||
"@babel/code-frame@^7.0.0":
|
"@babel/code-frame@^7.0.0":
|
||||||
version "7.16.0"
|
version "7.16.0"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431"
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431"
|
||||||
@ -1563,6 +1571,13 @@ onetime@^5.1.0, onetime@^5.1.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mimic-fn "^2.1.0"
|
mimic-fn "^2.1.0"
|
||||||
|
|
||||||
|
openapi3-ts@^2.0.2:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/openapi3-ts/-/openapi3-ts-2.0.2.tgz#a200dd838bf24c9086c8eedcfeb380b7eb31e82a"
|
||||||
|
integrity sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==
|
||||||
|
dependencies:
|
||||||
|
yaml "^1.10.2"
|
||||||
|
|
||||||
optionator@^0.9.1:
|
optionator@^0.9.1:
|
||||||
version "0.9.1"
|
version "0.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
|
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
|
||||||
@ -2042,6 +2057,11 @@ tree-kill@^1.2.2:
|
|||||||
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
||||||
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
|
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
|
||||||
|
|
||||||
|
ts-deepmerge@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-deepmerge/-/ts-deepmerge-1.1.0.tgz#4236ae102199affe2e77690dcf198a420160eef2"
|
||||||
|
integrity sha512-VvwaV/6RyYMwT9d8dClmfHIsG2PCdm6WY430QKOIbPRR50Y/1Q2ilp4i2XEZeHFcNqfaYnAQzpyUC6XA0AqqBg==
|
||||||
|
|
||||||
ts-node-dev@^1.1.8:
|
ts-node-dev@^1.1.8:
|
||||||
version "1.1.8"
|
version "1.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-1.1.8.tgz#95520d8ab9d45fffa854d6668e2f8f9286241066"
|
resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-1.1.8.tgz#95520d8ab9d45fffa854d6668e2f8f9286241066"
|
||||||
@ -2153,6 +2173,11 @@ v8-compile-cache@^2.0.3:
|
|||||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
||||||
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
|
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
|
||||||
|
|
||||||
|
validator@^13.7.0:
|
||||||
|
version "13.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857"
|
||||||
|
integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==
|
||||||
|
|
||||||
webidl-conversions@^3.0.0:
|
webidl-conversions@^3.0.0:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||||
@ -2236,7 +2261,7 @@ yallist@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||||
|
|
||||||
yaml@^1.10.0:
|
yaml@^1.10.0, yaml@^1.10.2:
|
||||||
version "1.10.2"
|
version "1.10.2"
|
||||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@16bits/nes.css": "^2.3.2",
|
"@16bits/nes.css": "^2.3.2",
|
||||||
|
"@anatine/zod-openapi": "^1.3.0",
|
||||||
"@fontsource/press-start-2p": "^4.3.0",
|
"@fontsource/press-start-2p": "^4.3.0",
|
||||||
"@joeattardi/emoji-button": "^4.6.2",
|
"@joeattardi/emoji-button": "^4.6.2",
|
||||||
"@types/simple-peer": "^9.11.1",
|
"@types/simple-peer": "^9.11.1",
|
||||||
@ -46,6 +47,7 @@
|
|||||||
"easystarjs": "^0.4.4",
|
"easystarjs": "^0.4.4",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"google-protobuf": "^3.13.0",
|
"google-protobuf": "^3.13.0",
|
||||||
|
"openapi3-ts": "^2.0.2",
|
||||||
"phaser": "3.55.1",
|
"phaser": "3.55.1",
|
||||||
"phaser-animated-tiles": "workadventure/phaser-animated-tiles#da68bbededd605925621dd4f03bd27e69284b254",
|
"phaser-animated-tiles": "workadventure/phaser-animated-tiles#da68bbededd605925621dd4f03bd27e69284b254",
|
||||||
"phaser3-rex-plugins": "^1.1.42",
|
"phaser3-rex-plugins": "^1.1.42",
|
||||||
|
@ -7,6 +7,14 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@16bits/nes.css/-/nes.css-2.3.2.tgz#e69db834119b33ae8d3cb044f106a07a17cadd6f"
|
resolved "https://registry.yarnpkg.com/@16bits/nes.css/-/nes.css-2.3.2.tgz#e69db834119b33ae8d3cb044f106a07a17cadd6f"
|
||||||
integrity sha512-nEM5PIth+Bab5JSOa4uUR+PMNUsNTYxA55oVlG3gXI/4LoYtWS767Uv9Pu/KCbHXVvnIjt4ZXt13kZw3083qTw==
|
integrity sha512-nEM5PIth+Bab5JSOa4uUR+PMNUsNTYxA55oVlG3gXI/4LoYtWS767Uv9Pu/KCbHXVvnIjt4ZXt13kZw3083qTw==
|
||||||
|
|
||||||
|
"@anatine/zod-openapi@^1.3.0":
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@anatine/zod-openapi/-/zod-openapi-1.3.0.tgz#b5b38c3d821b79674226aa7b327c88c371860d0d"
|
||||||
|
integrity sha512-l54DypUdDsIq1Uwjv4ib9IBkTXMKZQLUj7qvdFL51EExC5LdSSqOlTOyaVVZZGYgWPKM7ZjGklhdoknLz4EC+w==
|
||||||
|
dependencies:
|
||||||
|
ts-deepmerge "^1.1.0"
|
||||||
|
validator "^13.7.0"
|
||||||
|
|
||||||
"@babel/runtime@^7.14.0":
|
"@babel/runtime@^7.14.0":
|
||||||
version "7.14.0"
|
version "7.14.0"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
|
||||||
@ -2055,6 +2063,13 @@ onetime@^5.1.0, onetime@^5.1.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mimic-fn "^2.1.0"
|
mimic-fn "^2.1.0"
|
||||||
|
|
||||||
|
openapi3-ts@^2.0.2:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/openapi3-ts/-/openapi3-ts-2.0.2.tgz#a200dd838bf24c9086c8eedcfeb380b7eb31e82a"
|
||||||
|
integrity sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==
|
||||||
|
dependencies:
|
||||||
|
yaml "^1.10.2"
|
||||||
|
|
||||||
optionator@^0.9.1:
|
optionator@^0.9.1:
|
||||||
version "0.9.1"
|
version "0.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
|
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
|
||||||
@ -2875,6 +2890,11 @@ to-regex-range@^5.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-number "^7.0.0"
|
is-number "^7.0.0"
|
||||||
|
|
||||||
|
ts-deepmerge@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-deepmerge/-/ts-deepmerge-1.1.0.tgz#4236ae102199affe2e77690dcf198a420160eef2"
|
||||||
|
integrity sha512-VvwaV/6RyYMwT9d8dClmfHIsG2PCdm6WY430QKOIbPRR50Y/1Q2ilp4i2XEZeHFcNqfaYnAQzpyUC6XA0AqqBg==
|
||||||
|
|
||||||
ts-deferred@^1.0.4:
|
ts-deferred@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/ts-deferred/-/ts-deferred-1.0.4.tgz#58145ebaeef5b8f2a290b8cec3d060839f9489c7"
|
resolved "https://registry.yarnpkg.com/ts-deferred/-/ts-deferred-1.0.4.tgz#58145ebaeef5b8f2a290b8cec3d060839f9489c7"
|
||||||
@ -3066,6 +3086,11 @@ validate-npm-package-license@^3.0.1:
|
|||||||
spdx-correct "^3.0.0"
|
spdx-correct "^3.0.0"
|
||||||
spdx-expression-parse "^3.0.0"
|
spdx-expression-parse "^3.0.0"
|
||||||
|
|
||||||
|
validator@^13.7.0:
|
||||||
|
version "13.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857"
|
||||||
|
integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==
|
||||||
|
|
||||||
vite-plugin-rewrite-all@^0.1.2:
|
vite-plugin-rewrite-all@^0.1.2:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/vite-plugin-rewrite-all/-/vite-plugin-rewrite-all-0.1.2.tgz#312bbcd76c700ceac5153bfc5ad7e3e3e4bc9606"
|
resolved "https://registry.yarnpkg.com/vite-plugin-rewrite-all/-/vite-plugin-rewrite-all-0.1.2.tgz#312bbcd76c700ceac5153bfc5ad7e3e3e4bc9606"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
import {extendApi} from "@anatine/zod-openapi";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WARNING! The original file is in /messages/JsonMessages.
|
* WARNING! The original file is in /messages/JsonMessages.
|
||||||
@ -6,10 +7,11 @@ import { z } from "zod";
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export const isAdminApiData = z.object({
|
export const isAdminApiData = z.object({
|
||||||
userUuid: z.string(),
|
// @ts-ignore
|
||||||
email: z.nullable(z.string()),
|
userUuid: extendApi(z.string(), {example: '998ce839-3dea-4698-8b41-ebbdf7688ad9'}),
|
||||||
roomUrl: z.string(),
|
email: extendApi(z.nullable(z.string()), {description: 'The email of the current user.', example: 'example@workadventu.re'}),
|
||||||
mapUrlStart: z.string(),
|
roomUrl: extendApi(z.string(), {example: '/@/teamSlug/worldSlug/roomSlug'}),
|
||||||
|
mapUrlStart: extendApi(z.string(), {description: 'The full URL to the JSON map file', example: 'https://myuser.github.io/myrepo/map.json'}),
|
||||||
messages: z.optional(z.array(z.unknown())),
|
messages: z.optional(z.array(z.unknown())),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,46 +1,69 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
import {extendApi} from "@anatine/zod-openapi";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WARNING! The original file is in /messages/JsonMessages.
|
* WARNING! The original file is in /messages/JsonMessages.
|
||||||
* All other files are automatically copied from this file on container startup / build
|
* All other files are automatically copied from this file on container startup / build
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const isErrorApiErrorData = z.object({
|
export const isErrorApiErrorData = extendApi(
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
type: z.literal("error"),
|
z.object({
|
||||||
code: z.string(),
|
type: z.literal("error"),
|
||||||
title: z.string(),
|
code: extendApi(z.string(), {description: 'The system code of an error, it must be in SCREAMING_SNAKE_CASE.', example: 'ROOM_NOT_FOUND'}),
|
||||||
subtitle: z.string(),
|
title: extendApi(z.string(), {description: "Big title displayed on the error screen.", example: "ERROR"}),
|
||||||
details: z.string(),
|
subtitle: extendApi(z.string(), {description: "Subtitle displayed to let the user know what is the main subject of the error.", example: "The room was not found."}),
|
||||||
image: z.string(),
|
details: extendApi(z.string(), {description: "Some others details on what the user can do if he don't understand the error.", example: "If you would like more information, you can contact the administrator or us at example@workadventu.re."}),
|
||||||
});
|
image: extendApi(z.string(), {description: "The URL of the image displayed just under the logo in the error screen.", example: 'https://example.com/error.png'}),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
description: 'This is an error that can be returned by the API, its type must be equal to "error".\n If such an error is caught, an error screen will be displayed.',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const isErrorApiRetryData = z.object({
|
export const isErrorApiRetryData = extendApi(
|
||||||
type: z.literal("retry"),
|
z.object({
|
||||||
code: z.string(),
|
type: z.literal("retry"),
|
||||||
title: z.string(),
|
code: extendApi(z.string(), {description: 'The system code of an error, it must be in SCREAMING_SNAKE_CASE. \n It will not be displayed to the user.', example: 'WORLD_FULL'}),
|
||||||
subtitle: z.string(),
|
title: extendApi(z.string(), {description: "Big title displayed on the error screen.", example: "ERROR"}),
|
||||||
details: z.string(),
|
subtitle: extendApi(z.string(), {description: "Subtitle displayed to let the user know what is the main subject of the error.", example: "Too successful, your WorkAdventure world is full!"}),
|
||||||
image: z.string(),
|
details: extendApi(z.string(), {description: "Some others details on what the user can do if he don't understand the error.", example: "New automatic attempt in 30 seconds"}),
|
||||||
buttonTitle: z.optional(z.nullable(z.string())),
|
image: extendApi(z.string(), {description: "The URL of the image displayed just under the logo in the waiting screen.", example: 'https://example.com/wait.png'}),
|
||||||
timeToRetry: z.number(),
|
buttonTitle: extendApi(z.optional(z.nullable(z.string())), {description: "If this is not defined the button and the parameter canRetryManual is set to true, the button will be not displayed at all.", example: "Retry"}),
|
||||||
canRetryManual: z.boolean(),
|
timeToRetry: extendApi(z.number(), {description: "This is the time (in millisecond) between the next auto refresh of the page.", example: 30_000}),
|
||||||
});
|
canRetryManual: extendApi(z.boolean(), {description: "This boolean show or hide the button to let the user refresh manually the current page.", example: true}),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
description: 'This is an error that can be returned by the API, its type must be equal to "retry".\n' +
|
||||||
|
'If such an error is caught, a waiting screen will be displayed.',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const isErrorApiRedirectData = z.object({
|
export const isErrorApiRedirectData = extendApi(
|
||||||
type: z.literal("redirect"),
|
z.object({
|
||||||
urlToRedirect: z.string(),
|
type: z.literal("redirect"),
|
||||||
});
|
urlToRedirect: extendApi(z.string(), {description: 'A URL specified to redirect the user onto it directly', example: '/contact-us'}),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
description: 'This is an error that can be returned by the API, its type must be equal to "redirect".\n' +
|
||||||
|
'If such an error is caught, the user will be automatically redirected to urlToRedirect.',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const isErrorApiUnauthorizedData = z.object({
|
export const isErrorApiUnauthorizedData = extendApi(
|
||||||
type: z.literal("unauthorized"),
|
z.object({
|
||||||
code: z.string(),
|
type: z.literal("unauthorized"),
|
||||||
title: z.string(),
|
code: extendApi(z.string(), {description: "This is the system code of an error, it must be in SCREAMING_SNAKE_CASE.", example: "USER_ACCESS_FORBIDDEN"}),
|
||||||
subtitle: z.string(),
|
title: extendApi(z.string(), {description: "Big title displayed on the error screen.", example: "ERROR"}),
|
||||||
details: z.string(),
|
subtitle: extendApi(z.string(), {description: "Subtitle displayed to let the user know what is the main subject of the error.", example: "You can't access this place."}),
|
||||||
image: z.string(),
|
details: extendApi(z.string(), {description: "Some others details on what the user can do if he don't understand the error.", example: "If you would like more information, you can contact the administrator or us at example@workadventu.re."}),
|
||||||
buttonTitle: z.optional(z.nullable(z.string())),
|
image: extendApi(z.string(), {description: "The URL of the image displayed just under the logo in the error screen.", example: 'https://example.com/error.png'}),
|
||||||
});
|
buttonTitle: extendApi(z.optional(z.nullable(z.string())), {description: "If this is not defined the button to logout will be not displayed.", example: "Log out"}),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
description: 'This is an error that can be returned by the API, its type must be equal to "unauthorized".\n' +
|
||||||
|
'If such an error is caught, an error screen will be displayed with a button to let him logout and go to login page.',
|
||||||
|
});
|
||||||
|
|
||||||
export const isErrorApiData = z.discriminatedUnion("type", [
|
export const isErrorApiData = z.discriminatedUnion("type", [
|
||||||
isErrorApiErrorData,
|
isErrorApiErrorData,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
import {extendApi} from "@anatine/zod-openapi";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WARNING! The original file is in /messages/JsonMessages.
|
* WARNING! The original file is in /messages/JsonMessages.
|
||||||
@ -6,20 +7,21 @@ import { z } from "zod";
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export const isMapDetailsData = z.object({
|
export const isMapDetailsData = z.object({
|
||||||
mapUrl: z.string(),
|
// @ts-ignore
|
||||||
authenticationMandatory: z.optional(z.nullable(z.boolean())),
|
mapUrl: extendApi(z.string(), {description: 'The full URL to the JSON map file', example: 'https://myuser.github.io/myrepo/map.json'}),
|
||||||
group: z.nullable(z.string()),
|
authenticationMandatory: extendApi(z.optional(z.nullable(z.boolean())), {description: 'Whether the authentication is mandatory or not for this map', example: true}),
|
||||||
|
group: extendApi(z.nullable(z.string()), {description: 'The group this room is part of (maps the notion of "world" in WorkAdventure SAAS)', example: 'myorg/myworld'}),
|
||||||
|
|
||||||
contactPage: z.optional(z.nullable(z.string())),
|
contactPage: extendApi(z.optional(z.nullable(z.string())), {description: 'The URL to the contact page', example: 'https://mycompany.com/contact-us'}),
|
||||||
iframeAuthentication: z.optional(z.nullable(z.string())),
|
iframeAuthentication: extendApi(z.optional(z.nullable(z.string())), {description: 'The URL of the authentication Iframe', example: 'https://mycompany.com/authc'}),
|
||||||
// The date (in ISO 8601 format) at which the room will expire
|
// The date (in ISO 8601 format) at which the room will expire
|
||||||
expireOn: z.optional(z.string()),
|
expireOn: extendApi(z.optional(z.string()), {description: 'The date (in ISO 8601 format) at which the room will expire', example: '2022-11-05T08:15:30-05:00'}),
|
||||||
// Whether the "report" feature is enabled or not on this room
|
// Whether the "report" feature is enabled or not on this room
|
||||||
canReport: z.optional(z.boolean()),
|
canReport: extendApi(z.optional(z.boolean()), {description: 'Whether the "report" feature is enabled or not on this room', example: true}),
|
||||||
// The URL of the logo image on the loading screen
|
// The URL of the logo image on the loading screen
|
||||||
loadingLogo: z.optional(z.nullable(z.string())),
|
loadingLogo: extendApi(z.optional(z.nullable(z.string())), {description: 'The URL of the image to be used on the loading page', example: 'https://example.com/logo.png'}),
|
||||||
// The URL of the logo image on "LoginScene"
|
// The URL of the logo image on "LoginScene"
|
||||||
loginSceneLogo: z.optional(z.nullable(z.string())),
|
loginSceneLogo: extendApi(z.optional(z.nullable(z.string())), {description: 'The URL of the image to be used on the LoginScene', example: 'https://example.com/logo_login.png'}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type MapDetailsData = z.infer<typeof isMapDetailsData>;
|
export type MapDetailsData = z.infer<typeof isMapDetailsData>;
|
||||||
|
@ -18,8 +18,10 @@
|
|||||||
"pretty-check": "yarn prettier --check 'JsonMessages/**/*.ts'"
|
"pretty-check": "yarn prettier --check 'JsonMessages/**/*.ts'"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@anatine/zod-openapi": "^1.3.0",
|
||||||
"google-protobuf": "^3.13.0",
|
"google-protobuf": "^3.13.0",
|
||||||
"grpc": "^1.24.4",
|
"grpc": "^1.24.4",
|
||||||
|
"openapi3-ts": "^2.0.2",
|
||||||
"ts-proto": "^1.96.0",
|
"ts-proto": "^1.96.0",
|
||||||
"zod": "^3.14.3"
|
"zod": "^3.14.3"
|
||||||
},
|
},
|
||||||
|
@ -2,6 +2,14 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@anatine/zod-openapi@^1.3.0":
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@anatine/zod-openapi/-/zod-openapi-1.3.0.tgz#b5b38c3d821b79674226aa7b327c88c371860d0d"
|
||||||
|
integrity sha512-l54DypUdDsIq1Uwjv4ib9IBkTXMKZQLUj7qvdFL51EExC5LdSSqOlTOyaVVZZGYgWPKM7ZjGklhdoknLz4EC+w==
|
||||||
|
dependencies:
|
||||||
|
ts-deepmerge "^1.1.0"
|
||||||
|
validator "^13.7.0"
|
||||||
|
|
||||||
"@babel/code-frame@^7.0.0":
|
"@babel/code-frame@^7.0.0":
|
||||||
version "7.10.4"
|
version "7.10.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
|
||||||
@ -3241,6 +3249,13 @@ onetime@^5.1.0, onetime@^5.1.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mimic-fn "^2.1.0"
|
mimic-fn "^2.1.0"
|
||||||
|
|
||||||
|
openapi3-ts@^2.0.2:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/openapi3-ts/-/openapi3-ts-2.0.2.tgz#a200dd838bf24c9086c8eedcfeb380b7eb31e82a"
|
||||||
|
integrity sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==
|
||||||
|
dependencies:
|
||||||
|
yaml "^1.10.2"
|
||||||
|
|
||||||
optionator@^0.9.1:
|
optionator@^0.9.1:
|
||||||
version "0.9.1"
|
version "0.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
|
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
|
||||||
@ -4284,6 +4299,11 @@ tough-cookie@~2.5.0:
|
|||||||
psl "^1.1.28"
|
psl "^1.1.28"
|
||||||
punycode "^2.1.1"
|
punycode "^2.1.1"
|
||||||
|
|
||||||
|
ts-deepmerge@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-deepmerge/-/ts-deepmerge-1.1.0.tgz#4236ae102199affe2e77690dcf198a420160eef2"
|
||||||
|
integrity sha512-VvwaV/6RyYMwT9d8dClmfHIsG2PCdm6WY430QKOIbPRR50Y/1Q2ilp4i2XEZeHFcNqfaYnAQzpyUC6XA0AqqBg==
|
||||||
|
|
||||||
ts-poet@^4.5.0:
|
ts-poet@^4.5.0:
|
||||||
version "4.6.1"
|
version "4.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/ts-poet/-/ts-poet-4.6.1.tgz#015dc823d726655af9f095c900f84ed7c60e2dd3"
|
resolved "https://registry.yarnpkg.com/ts-poet/-/ts-poet-4.6.1.tgz#015dc823d726655af9f095c900f84ed7c60e2dd3"
|
||||||
@ -4487,6 +4507,11 @@ validate-npm-package-name@^3.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
builtins "^1.0.3"
|
builtins "^1.0.3"
|
||||||
|
|
||||||
|
validator@^13.7.0:
|
||||||
|
version "13.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857"
|
||||||
|
integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==
|
||||||
|
|
||||||
verror@1.10.0:
|
verror@1.10.0:
|
||||||
version "1.10.0"
|
version "1.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
|
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
|
||||||
@ -4593,7 +4618,7 @@ yallist@^3.0.0, yallist@^3.0.3:
|
|||||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||||
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
||||||
|
|
||||||
yaml@^1.10.0:
|
yaml@^1.10.0, yaml@^1.10.2:
|
||||||
version "1.10.2"
|
version "1.10.2"
|
||||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import { BaseHttpController } from "./BaseHttpController";
|
import { BaseHttpController } from "./BaseHttpController";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
|
import { ADMIN_URL } from "../Enum/EnvironmentVariable";
|
||||||
|
import SwaggerGenerator from "../Services/SwaggerGenerator";
|
||||||
|
import swaggerJsdoc from "swagger-jsdoc";
|
||||||
|
|
||||||
export class SwaggerController extends BaseHttpController {
|
export class SwaggerController extends BaseHttpController {
|
||||||
routes() {
|
routes() {
|
||||||
this.app.get("/openapi", (req, res) => {
|
this.app.get("/openapi/pusher", (req, res) => {
|
||||||
// Let's load the module dynamically (it may not exist in prod because part of the -dev packages)
|
// Let's load the module dynamically (it may not exist in prod because part of the -dev packages)
|
||||||
const swaggerJsdoc = require("swagger-jsdoc");
|
const swaggerJsdoc = require("swagger-jsdoc");
|
||||||
const options = {
|
const options = {
|
||||||
@ -20,6 +23,43 @@ export class SwaggerController extends BaseHttpController {
|
|||||||
res.json(swaggerJsdoc(options));
|
res.json(swaggerJsdoc(options));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.app.get("/openapi/admin", (req, res) => {
|
||||||
|
// Let's load the module dynamically (it may not exist in prod because part of the -dev packages)
|
||||||
|
const swaggerJsdoc = require("swagger-jsdoc");
|
||||||
|
const options = {
|
||||||
|
swaggerDefinition: {
|
||||||
|
swagger: "2.0",
|
||||||
|
//openapi: "3.0.0",
|
||||||
|
info: {
|
||||||
|
title: "WorkAdventure Pusher",
|
||||||
|
version: "1.0.0",
|
||||||
|
description: "This is a documentation about the endpoints called by the pusher. \n You can find out more about WorkAdventure on [github](https://github.com/thecodingmachine/workadventure).",
|
||||||
|
contact:
|
||||||
|
{
|
||||||
|
email: "hello@workadventu.re"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"host": "pusher." + ADMIN_URL.replace('//',''),
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"name": "AdminAPI",
|
||||||
|
"description": "Access to end points of the admin from the pusher"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"securityDefinitions": {
|
||||||
|
"Bearer": {
|
||||||
|
"type": "apiKey",
|
||||||
|
"name": "Authorization",
|
||||||
|
"in": "header"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...SwaggerGenerator.definitions()
|
||||||
|
},
|
||||||
|
apis: ["./src/Services/*.ts"],
|
||||||
|
};
|
||||||
|
res.json(swaggerJsdoc(options));
|
||||||
|
});
|
||||||
|
|
||||||
// Create a LiveDirectory instance to virtualize directory with our assets
|
// Create a LiveDirectory instance to virtualize directory with our assets
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const LiveDirectory = require("live-directory");
|
const LiveDirectory = require("live-directory");
|
||||||
@ -39,8 +79,13 @@ export class SwaggerController extends BaseHttpController {
|
|||||||
if (err) {
|
if (err) {
|
||||||
return response.status(500).send(err.message);
|
return response.status(500).send(err.message);
|
||||||
}
|
}
|
||||||
const result = data.replace(/https:\/\/petstore\.swagger\.io\/v2\/swagger.json/g, "/openapi");
|
|
||||||
|
|
||||||
|
const urls = [
|
||||||
|
{url: "/openapi/pusher", name: "Front -> Pusher"},
|
||||||
|
{url: "/openapi/admin", name: "Pusher <- Admin"},
|
||||||
|
];
|
||||||
|
|
||||||
|
const result = data.replace(/url: "https:\/\/petstore\.swagger\.io\/v2\/swagger.json"/g, `urls: ${JSON.stringify(urls)}, "urls.primaryName": "Pusher <- Admin"`);
|
||||||
response.send(result);
|
response.send(result);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
import {extendApi} from "@anatine/zod-openapi";
|
||||||
|
|
||||||
export const isBanBannedAdminMessageInterface = z.object({
|
export const isBanBannedAdminMessageInterface = z.object({
|
||||||
type: z.enum(["ban", "banned"]),
|
type: z.enum(["ban", "banned"]),
|
||||||
@ -8,7 +9,7 @@ export const isBanBannedAdminMessageInterface = z.object({
|
|||||||
|
|
||||||
export const isUserMessageAdminMessageInterface = z.object({
|
export const isUserMessageAdminMessageInterface = z.object({
|
||||||
event: z.enum(["user-message"]),
|
event: z.enum(["user-message"]),
|
||||||
message: isBanBannedAdminMessageInterface,
|
message: extendApi(isBanBannedAdminMessageInterface, {$ref: "#/definitions/BanBannedAdminMessageInterface"}),
|
||||||
world: z.string(),
|
world: z.string(),
|
||||||
jwt: z.string(),
|
jwt: z.string(),
|
||||||
});
|
});
|
||||||
|
@ -9,6 +9,7 @@ import qs from "qs";
|
|||||||
import { AdminInterface } from "./AdminInterface";
|
import { AdminInterface } from "./AdminInterface";
|
||||||
import { AuthTokenData, jwtTokenManager } from "./JWTTokenManager";
|
import { AuthTokenData, jwtTokenManager } from "./JWTTokenManager";
|
||||||
import { InvalidTokenError } from "../Controller/InvalidTokenError";
|
import { InvalidTokenError } from "../Controller/InvalidTokenError";
|
||||||
|
import {extendApi} from "@anatine/zod-openapi";
|
||||||
|
|
||||||
export interface AdminBannedData {
|
export interface AdminBannedData {
|
||||||
is_banned: boolean;
|
is_banned: boolean;
|
||||||
@ -16,15 +17,16 @@ export interface AdminBannedData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const isFetchMemberDataByUuidResponse = z.object({
|
export const isFetchMemberDataByUuidResponse = z.object({
|
||||||
email: z.string(),
|
// @ts-ignore
|
||||||
userUuid: z.string(),
|
email: extendApi(z.string(), {description: 'The email of the fetched user, it can be an email, an uuid or undefined.', example: "example@workadventu.re"}),
|
||||||
tags: z.array(z.string()),
|
userUuid: extendApi(z.string(), {description: 'The uuid of the fetched user, it can be an email, an uuid or undefined.', example: "998ce839-3dea-4698-8b41-ebbdf7688ad9"}),
|
||||||
visitCardUrl: z.nullable(z.string()),
|
tags: extendApi(z.array(z.string()), {description: 'List of tags related to the user fetched.', example: ['editor']}),
|
||||||
textures: z.array(isWokaDetail),
|
visitCardUrl: extendApi(z.nullable(z.string()), {description: 'URL of the visitCard of the user fetched.', example: 'https://mycompany.com/contact/me'}),
|
||||||
messages: z.array(z.unknown()),
|
textures: extendApi(z.array(isWokaDetail), {$ref: "#/definitions/WokaDetail"}),
|
||||||
|
messages: extendApi(z.array(z.unknown()), {description: 'List of user\'s messages.'}),
|
||||||
|
|
||||||
anonymous: z.optional(z.boolean()),
|
anonymous: extendApi(z.optional(z.boolean()), {description: 'Whether the user if logged as anonymous or not', example: false}),
|
||||||
userRoomToken: z.optional(z.string()),
|
userRoomToken: extendApi(z.optional(z.string()), {description: '', example: ''}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type FetchMemberDataByUuidResponse = z.infer<typeof isFetchMemberDataByUuidResponse>;
|
export type FetchMemberDataByUuidResponse = z.infer<typeof isFetchMemberDataByUuidResponse>;
|
||||||
@ -69,6 +71,47 @@ class AdminApi implements AdminInterface {
|
|||||||
userId,
|
userId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @openapi
|
||||||
|
* /api/map:
|
||||||
|
* get:
|
||||||
|
* tags: ["AdminAPI"]
|
||||||
|
* description: Returns a map mapping map name to file name of the map
|
||||||
|
* security:
|
||||||
|
* - Bearer: []
|
||||||
|
* produces:
|
||||||
|
* - "application/json"
|
||||||
|
* parameters:
|
||||||
|
* - name: "playUri"
|
||||||
|
* in: "query"
|
||||||
|
* description: "The full URL of WorkAdventure"
|
||||||
|
* required: true
|
||||||
|
* type: "string"
|
||||||
|
* example: "http://play.workadventure.localhost/@/teamSlug/worldSLug/roomSlug"
|
||||||
|
* - name: "userId"
|
||||||
|
* in: "query"
|
||||||
|
* description: "The identifier of the current user \n It can be undefined or an uuid or an email"
|
||||||
|
* type: "string"
|
||||||
|
* example: "998ce839-3dea-4698-8b41-ebbdf7688ad9"
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The details of the member
|
||||||
|
* schema:
|
||||||
|
* $ref: "#/definitions/MapDetailsData"
|
||||||
|
* 401:
|
||||||
|
* description: Error while retrieving the data because you are not authorized
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/definitions/ErrorApiRedirectData'
|
||||||
|
* 403:
|
||||||
|
* description: Error while retrieving the data because you are not authorized
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/definitions/ErrorApiUnauthorizedData'
|
||||||
|
* 404:
|
||||||
|
* description: Error while retrieving the data
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/definitions/ErrorApiErrorData'
|
||||||
|
*
|
||||||
|
*/
|
||||||
const res = await Axios.get<unknown, AxiosResponse<unknown>>(ADMIN_API_URL + "/api/map", {
|
const res = await Axios.get<unknown, AxiosResponse<unknown>>(ADMIN_API_URL + "/api/map", {
|
||||||
headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": locale ?? "en" },
|
headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": locale ?? "en" },
|
||||||
params,
|
params,
|
||||||
@ -99,6 +142,58 @@ class AdminApi implements AdminInterface {
|
|||||||
characterLayers: string[],
|
characterLayers: string[],
|
||||||
locale?: string
|
locale?: string
|
||||||
): Promise<FetchMemberDataByUuidResponse> {
|
): Promise<FetchMemberDataByUuidResponse> {
|
||||||
|
/**
|
||||||
|
* @openapi
|
||||||
|
* /api/room/access:
|
||||||
|
* get:
|
||||||
|
* tags: ["AdminAPI"]
|
||||||
|
* description: Returns member's informations if he can access this room
|
||||||
|
* security:
|
||||||
|
* - Bearer: []
|
||||||
|
* produces:
|
||||||
|
* - "application/json"
|
||||||
|
* parameters:
|
||||||
|
* - name: "userIdentifier"
|
||||||
|
* in: "query"
|
||||||
|
* description: "The identifier of the current user \n It can be undefined or an uuid or an email"
|
||||||
|
* type: "string"
|
||||||
|
* example: "998ce839-3dea-4698-8b41-ebbdf7688ad9"
|
||||||
|
* - name: "playUri"
|
||||||
|
* in: "query"
|
||||||
|
* description: "The full URL of WorkAdventure"
|
||||||
|
* required: true
|
||||||
|
* type: "string"
|
||||||
|
* example: "http://play.workadventure.localhost/@/teamSlug/worldSLug/roomSlug"
|
||||||
|
* - name: "ipAddress"
|
||||||
|
* in: "query"
|
||||||
|
* required: true
|
||||||
|
* type: "string"
|
||||||
|
* example: "127.0.0.1"
|
||||||
|
* - name: "characterLayers"
|
||||||
|
* in: "query"
|
||||||
|
* type: "array"
|
||||||
|
* items:
|
||||||
|
* type: string
|
||||||
|
* example: ["male1"]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The details of the member
|
||||||
|
* schema:
|
||||||
|
* $ref: "#/definitions/FetchMemberDataByUuidResponse"
|
||||||
|
* 401:
|
||||||
|
* description: Error while retrieving the data because you are not authorized
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/definitions/ErrorApiRedirectData'
|
||||||
|
* 403:
|
||||||
|
* description: Error while retrieving the data because you are not authorized
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/definitions/ErrorApiUnauthorizedData'
|
||||||
|
* 404:
|
||||||
|
* description: Error while retrieving the data
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/definitions/ErrorApiErrorData'
|
||||||
|
*
|
||||||
|
*/
|
||||||
const res = await Axios.get<unknown, AxiosResponse<unknown>>(ADMIN_API_URL + "/api/room/access", {
|
const res = await Axios.get<unknown, AxiosResponse<unknown>>(ADMIN_API_URL + "/api/room/access", {
|
||||||
params: {
|
params: {
|
||||||
userIdentifier,
|
userIdentifier,
|
||||||
@ -130,6 +225,42 @@ class AdminApi implements AdminInterface {
|
|||||||
playUri: string | null,
|
playUri: string | null,
|
||||||
locale?: string
|
locale?: string
|
||||||
): Promise<AdminApiData> {
|
): Promise<AdminApiData> {
|
||||||
|
/**
|
||||||
|
* @openapi
|
||||||
|
* /api/login-url/{organizationMemberToken}:
|
||||||
|
* get:
|
||||||
|
* tags: ["AdminAPI"]
|
||||||
|
* description: Returns a member from the token
|
||||||
|
* security:
|
||||||
|
* - Bearer: []
|
||||||
|
* produces:
|
||||||
|
* - "application/json"
|
||||||
|
* parameters:
|
||||||
|
* - name: "organizationMemberToken"
|
||||||
|
* in: "path"
|
||||||
|
* description: "The token of member in the organization"
|
||||||
|
* type: "string"
|
||||||
|
* - name: "playUri"
|
||||||
|
* in: "query"
|
||||||
|
* description: "The full URL of WorkAdventure"
|
||||||
|
* required: true
|
||||||
|
* type: "string"
|
||||||
|
* example: "http://play.workadventure.localhost/@/teamSlug/worldSLug/roomSlug"
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The details of the member
|
||||||
|
* schema:
|
||||||
|
* $ref: "#/definitions/AdminApiData"
|
||||||
|
* 401:
|
||||||
|
* description: Error while retrieving the data because you are not authorized
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/definitions/ErrorApiRedirectData'
|
||||||
|
* 404:
|
||||||
|
* description: Error while retrieving the data
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/definitions/ErrorApiErrorData'
|
||||||
|
*
|
||||||
|
*/
|
||||||
//todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case.
|
//todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case.
|
||||||
const res = await Axios.get(ADMIN_API_URL + "/api/login-url/" + organizationMemberToken, {
|
const res = await Axios.get(ADMIN_API_URL + "/api/login-url/" + organizationMemberToken, {
|
||||||
params: { playUri },
|
params: { playUri },
|
||||||
@ -154,6 +285,41 @@ class AdminApi implements AdminInterface {
|
|||||||
reportWorldSlug: string,
|
reportWorldSlug: string,
|
||||||
locale?: string
|
locale?: string
|
||||||
) {
|
) {
|
||||||
|
/**
|
||||||
|
* @openapi
|
||||||
|
* /api/report:
|
||||||
|
* post:
|
||||||
|
* tags: ["AdminAPI"]
|
||||||
|
* description: Report one user with a comment
|
||||||
|
* security:
|
||||||
|
* - Bearer: []
|
||||||
|
* produces:
|
||||||
|
* - "application/json"
|
||||||
|
* parameters:
|
||||||
|
* - name: "reportedUserUuid"
|
||||||
|
* in: "query"
|
||||||
|
* description: "The identifier of the reported user \n It can be an uuid or an email"
|
||||||
|
* type: "string"
|
||||||
|
* example: "998ce839-3dea-4698-8b41-ebbdf7688ad9"
|
||||||
|
* - name: "reportedUserComment"
|
||||||
|
* in: "query"
|
||||||
|
* description: "The comment of the report"
|
||||||
|
* required: true
|
||||||
|
* type: "string"
|
||||||
|
* - name: "reporterUserUuid"
|
||||||
|
* in: "query"
|
||||||
|
* description: "The identifier of the reporter user \n It can be an uuid or an email"
|
||||||
|
* type: "string"
|
||||||
|
* example: "998ce839-3dea-4698-8b41-ebbdf7688ad8"
|
||||||
|
* - name: "reportWorldSlug"
|
||||||
|
* in: "query"
|
||||||
|
* description: "The slug of the world where the report is made"
|
||||||
|
* type: "string"
|
||||||
|
* example: "/@/teamSlug/worldSlug/roomSlug"
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The report has been successfully saved
|
||||||
|
*/
|
||||||
return Axios.post(
|
return Axios.post(
|
||||||
`${ADMIN_API_URL}/api/report`,
|
`${ADMIN_API_URL}/api/report`,
|
||||||
{
|
{
|
||||||
@ -174,6 +340,53 @@ class AdminApi implements AdminInterface {
|
|||||||
roomUrl: string,
|
roomUrl: string,
|
||||||
locale?: string
|
locale?: string
|
||||||
): Promise<AdminBannedData> {
|
): Promise<AdminBannedData> {
|
||||||
|
/**
|
||||||
|
* @openapi
|
||||||
|
* /api/ban:
|
||||||
|
* get:
|
||||||
|
* tags: ["AdminAPI"]
|
||||||
|
* description: Check if user is banned or not
|
||||||
|
* security:
|
||||||
|
* - Bearer: []
|
||||||
|
* produces:
|
||||||
|
* - "application/json"
|
||||||
|
* parameters:
|
||||||
|
* - name: "ipAddress"
|
||||||
|
* in: "query"
|
||||||
|
* type: "string"
|
||||||
|
* required: true
|
||||||
|
* example: "127.0.0.1"
|
||||||
|
* - name: "token"
|
||||||
|
* in: "query"
|
||||||
|
* description: "The uuid of the user \n It can be an uuid or an email"
|
||||||
|
* type: "string"
|
||||||
|
* required: true
|
||||||
|
* example: "998ce839-3dea-4698-8b41-ebbdf7688ad8"
|
||||||
|
* - name: "roomUrl"
|
||||||
|
* in: "query"
|
||||||
|
* description: "The slug of the world where to check if the user is banned"
|
||||||
|
* type: "string"
|
||||||
|
* required: true
|
||||||
|
* example: "/@/teamSlug/worldSlug/roomSlug"
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The user is banned or not
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: array
|
||||||
|
* required:
|
||||||
|
* - is_banned
|
||||||
|
* properties:
|
||||||
|
* is_banned:
|
||||||
|
* type: boolean
|
||||||
|
* description: Whether the user is banned or not
|
||||||
|
* example: true
|
||||||
|
* 404:
|
||||||
|
* description: Error while retrieving the data
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/definitions/ErrorApiErrorData'
|
||||||
|
*/
|
||||||
//todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case.
|
//todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case.
|
||||||
return Axios.get(
|
return Axios.get(
|
||||||
ADMIN_API_URL +
|
ADMIN_API_URL +
|
||||||
@ -191,6 +404,37 @@ class AdminApi implements AdminInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getUrlRoomsFromSameWorld(roomUrl: string, locale?: string): Promise<string[]> {
|
async getUrlRoomsFromSameWorld(roomUrl: string, locale?: string): Promise<string[]> {
|
||||||
|
/**
|
||||||
|
* @openapi
|
||||||
|
* /api/room/sameWorld:
|
||||||
|
* get:
|
||||||
|
* tags: ["AdminAPI"]
|
||||||
|
* description: Get all URLs of the rooms from the world specified
|
||||||
|
* security:
|
||||||
|
* - Bearer: []
|
||||||
|
* produces:
|
||||||
|
* - "application/json"
|
||||||
|
* parameters:
|
||||||
|
* - name: "roomUrl"
|
||||||
|
* in: "query"
|
||||||
|
* description: "The slug of the room"
|
||||||
|
* type: "string"
|
||||||
|
* required: true
|
||||||
|
* example: "/@/teamSlug/worldSlug/roomSlug"
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The list of URL of the rooms from the same world
|
||||||
|
* schema:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* type: string
|
||||||
|
* description: URL of a room
|
||||||
|
* example: "http://example.com/@/teamSlug/worldSlug/room2Slug"
|
||||||
|
* 404:
|
||||||
|
* description: Error while retrieving the data
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/definitions/ErrorApiErrorData'
|
||||||
|
*/
|
||||||
return Axios.get(ADMIN_API_URL + "/api/room/sameWorld" + "?roomUrl=" + encodeURIComponent(roomUrl), {
|
return Axios.get(ADMIN_API_URL + "/api/room/sameWorld" + "?roomUrl=" + encodeURIComponent(roomUrl), {
|
||||||
headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": locale ?? "en" },
|
headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": locale ?? "en" },
|
||||||
}).then((data) => {
|
}).then((data) => {
|
||||||
@ -204,10 +448,6 @@ class AdminApi implements AdminInterface {
|
|||||||
}
|
}
|
||||||
return `${OPID_PROFILE_SCREEN_PROVIDER}?accessToken=${accessToken}`;
|
return `${OPID_PROFILE_SCREEN_PROVIDER}?accessToken=${accessToken}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async logoutOauth(token: string): Promise<void> {
|
|
||||||
await Axios.get(ADMIN_API_URL + `/oauth/logout?token=${token}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const adminApi = new AdminApi();
|
export const adminApi = new AdminApi();
|
||||||
|
@ -74,9 +74,4 @@ export interface AdminInterface {
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
getProfileUrl(accessToken: string): string;
|
getProfileUrl(accessToken: string): string;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token
|
|
||||||
*/
|
|
||||||
logoutOauth(token: string): Promise<void>;
|
|
||||||
}
|
}
|
||||||
|
@ -87,10 +87,6 @@ class LocalAdmin implements AdminInterface {
|
|||||||
new Error("No admin backoffice set!");
|
new Error("No admin backoffice set!");
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
async logoutOauth(token: string): Promise<void> {
|
|
||||||
return Promise.reject(new Error("No admin backoffice set!"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const localAdmin = new LocalAdmin();
|
export const localAdmin = new LocalAdmin();
|
||||||
|
42
pusher/src/Services/SwaggerGenerator.ts
Normal file
42
pusher/src/Services/SwaggerGenerator.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import {generateSchema} from "@anatine/zod-openapi";
|
||||||
|
import {isAdminApiData} from "../Messages/JsonMessages/AdminApiData";
|
||||||
|
import {
|
||||||
|
isErrorApiErrorData,
|
||||||
|
isErrorApiRedirectData,
|
||||||
|
isErrorApiRetryData,
|
||||||
|
isErrorApiUnauthorizedData
|
||||||
|
} from "../Messages/JsonMessages/ErrorApiData";
|
||||||
|
import {isMapDetailsData} from "../Messages/JsonMessages/MapDetailsData";
|
||||||
|
import {isRegisterData} from "../Messages/JsonMessages/RegisterData";
|
||||||
|
import {isRoomRedirect} from "../Messages/JsonMessages/RoomRedirect";
|
||||||
|
import {isFetchMemberDataByUuidResponse} from "./AdminApi";
|
||||||
|
import {
|
||||||
|
isBanBannedAdminMessageInterface, isListenRoomsMessageInterface,
|
||||||
|
isUserMessageAdminMessageInterface
|
||||||
|
} from "../Model/Websocket/Admin/AdminMessages";
|
||||||
|
import {isWokaDetail} from "../Messages/JsonMessages/PlayerTextures";
|
||||||
|
|
||||||
|
class SwaggerGenerator {
|
||||||
|
definitions() {
|
||||||
|
return {
|
||||||
|
definitions:
|
||||||
|
{
|
||||||
|
AdminApiData: generateSchema(isAdminApiData),
|
||||||
|
//BanBannedAdminMessageInterface: generateSchema(isBanBannedAdminMessageInterface),
|
||||||
|
ErrorApiErrorData: generateSchema(isErrorApiErrorData),
|
||||||
|
ErrorApiRedirectData: generateSchema(isErrorApiRedirectData),
|
||||||
|
ErrorApiRetryData: generateSchema(isErrorApiRetryData),
|
||||||
|
ErrorApiUnauthorizedData: generateSchema(isErrorApiUnauthorizedData),
|
||||||
|
FetchMemberDataByUuidResponse: generateSchema(isFetchMemberDataByUuidResponse),
|
||||||
|
//ListenRoomsMessageInterface: generateSchema(isListenRoomsMessageInterface),
|
||||||
|
MapDetailsData: generateSchema(isMapDetailsData),
|
||||||
|
//RegisterData: generateSchema(isRegisterData),
|
||||||
|
//RoomRedirect: generateSchema(isRoomRedirect),
|
||||||
|
//UserMessageAdminMessageInterface: generateSchema(isUserMessageAdminMessageInterface),
|
||||||
|
WokaDetail: generateSchema(isWokaDetail),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new SwaggerGenerator();
|
Loading…
Reference in New Issue
Block a user