summaryrefslogtreecommitdiff
path: root/rushs/eplace/server
diff options
context:
space:
mode:
Diffstat (limited to 'rushs/eplace/server')
-rw-r--r--rushs/eplace/server/.env36
-rw-r--r--rushs/eplace/server/config/default-canvas-250.txt1
-rw-r--r--rushs/eplace/server/config/default-canvas-50.txtbin0 -> 1563 bytes
-rw-r--r--rushs/eplace/server/config/rate-limits.config.json54
-rw-r--r--rushs/eplace/server/config/rooms.config.json39
-rw-r--r--rushs/eplace/server/docker-compose.yml56
-rw-r--r--rushs/eplace/server/openapi/openapi.json5064
7 files changed, 5250 insertions, 0 deletions
diff --git a/rushs/eplace/server/.env b/rushs/eplace/server/.env
new file mode 100644
index 0000000..7ff72e7
--- /dev/null
+++ b/rushs/eplace/server/.env
@@ -0,0 +1,36 @@
+# Environment variables declared in this file are automatically made available to Prisma.
+# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
+
+# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
+# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
+
+SERVER_PORT=3333
+WSS_PORT=3334
+
+POSTGRES_USER="postgres"
+POSTGRES_PASSWORD="postgres"
+POSTGRES_HOST="postgres"
+POSTGRES_PORT=5432
+POSTGRES_DB="eplace"
+POSTGRES_SCHEMA="public"
+DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?schema=${POSTGRES_SCHEMA}"
+
+
+REDIS_HOST="redis"
+REDIS_PORT=6379
+
+PUBLIC_API_URL="http://localhost:3333/api"
+JWKS_URI="https://cri.epita.fr/jwks"
+# DO NOT ERASE THIS UID, IT IS USE AS DEFAULT USER TO SETUP ROOMs, PIXELS
+# CHECK README FOR MORE DETAILS
+# You can add more admin uids by separating them with a comma
+# Example: 9361,9362,9363
+ADMIN_UID_LIST="9361"
+
+
+RATE_LIMITS_CONFIG_PATH="./config/rate-limits.config.json"
+ROOMS_CONFIG_PATH="./config/rooms.config.json"
+
+DISABLE_ADMIN_PREVILEGES="true"
+DISABLE_AUTH="false"
+DISABLE_RATE_LIMITING="false"
diff --git a/rushs/eplace/server/config/default-canvas-250.txt b/rushs/eplace/server/config/default-canvas-250.txt
new file mode 100644
index 0000000..9e52292
--- /dev/null
+++ b/rushs/eplace/server/config/default-canvas-250.txt
@@ -0,0 +1 @@
+B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B cB„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!BˆcÆ0„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„CÆ1ŒaB„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!BcÆ1ŒcÆ!!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!†1ŒcÆ1ŒcÆ1ŒcÆ!!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„"Æ1ŒcÆ1ŒcÆ1ŒcÆ1Œc‚„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„CÆ1ŒcÆ1ŒcÆ1ŒcÆ1ŒcÆ1ŒaB„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!BˆcÆ1ŒcÆ1Œb‚„"„1ŒcÆ1ŒcÆ „!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!BˆcÆ1ŒcÆ „!B„!B„!D1ŒcÆ1ŒcB„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!BˆcÆ1Œc‚„!B„C„!B„!Æ1ŒcÆ0„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!BˆcÆ1ŒcB„!B„#Æ1ˆ!B„!BˆcÆ1ŒcB„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„cÆ1ŒbB„!B„!Æ1ŒcB„!B„!F1ŒcÆ „!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„CÆ1ŒaB„!B„!Æ1ŒcÆ„!B„!B„CÆ1ŒaB„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„#Æ1ŒaB„!B„!B1ŒaÆ1ˆ!B„!B„!D1ŒcÄ„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„"Æ1ŒbB„!B„!BŒcBŒcB„!B„!B„cÆ1Œ!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!Æ1ŒbB„!B„!B„!„c„!B„!B„!F1Œc‚„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!Æ1ŒcB„!B„!B„!B„!Æ„!B„!B„!BˆcÆ1„!B„!B„!BˆBB„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!BˆcÆ1ŒcB„!B„!B„!B„!B„!B„!B„!B„!Æ1ŒcÆ0„!B„!BˆcÆ„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„cÆ1ŒcB„!B„!B„!B„!B„!B„!B„!B„!BŒcÆ1ŒbB„!BˆcÆ1Œ!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„"Æ1Œc„!BŒcÄ„!B„!B„!B„!B„!B„!B„"Æ1Œc„!B„cÆ1ŒcB„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!Æ1ŒcÄ„!B„cÆ1Œ!B„!B„!B„!B„!B1„!B„!B1ŒcÆ1!B„#Æ1ŒcÆ„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B1ŒcÆ „!B„"Æ1ŒcB„!B„!B„!B„!F1ŒcB„!B„cÆ1ŒAB„"Æ1ŒaÆ1!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!BŒcÆ1!B„!Æ1ˆCÆ„!B„!B„!B„!B1ŒcÆ0„!B„!Æ1ŒcB„!Æ1Œb
diff --git a/rushs/eplace/server/config/default-canvas-50.txt b/rushs/eplace/server/config/default-canvas-50.txt
new file mode 100644
index 0000000..ff61da9
--- /dev/null
+++ b/rushs/eplace/server/config/default-canvas-50.txt
Binary files differ
diff --git a/rushs/eplace/server/config/rate-limits.config.json b/rushs/eplace/server/config/rate-limits.config.json
new file mode 100644
index 0000000..aeb1cd2
--- /dev/null
+++ b/rushs/eplace/server/config/rate-limits.config.json
@@ -0,0 +1,54 @@
+{
+ "testsLimiter": {
+ "limit": 10,
+ "interval": 1
+ },
+ "getCanvasLimiter": {
+ "limit": 10,
+ "interval": 1
+ },
+ "getPixelLimiter": {
+ "limit": 10,
+ "interval": 1
+ },
+ "placePixelLimiter": {
+ "limit": 1,
+ "interval": 30
+ },
+ "getRoomsLimiter": {
+ "limit": 10,
+ "interval": 1
+ },
+ "getRoomConfigLimiter": {
+ "limit": 10,
+ "interval": 1
+ },
+ "createRoomLimiter": {
+ "limit": 1,
+ "interval": 300
+ },
+ "updateRoomLimiter": {
+ "limit": 1,
+ "interval": 1
+ },
+ "deleteRoomLimiter": {
+ "limit": 2,
+ "interval": 1
+ },
+ "getStudentLimiter": {
+ "limit": 10,
+ "interval": 1
+ },
+ "updateStudentLimiter": {
+ "limit": 1,
+ "interval": 1
+ },
+ "sendMessageLimiter": {
+ "limit": 1,
+ "interval": 1
+ },
+ "reportRoomLimiter": {
+ "limit": 1,
+ "interval": 5
+ }
+}
diff --git a/rushs/eplace/server/config/rooms.config.json b/rushs/eplace/server/config/rooms.config.json
new file mode 100644
index 0000000..b50080e
--- /dev/null
+++ b/rushs/eplace/server/config/rooms.config.json
@@ -0,0 +1,39 @@
+{
+ "maxRoomsCreatedPerUser": 3,
+ "rooms": {
+ "default": {
+ "metadata": {
+ "canvasDimensions": 50
+ },
+ "settings": {
+ "roomColors": "#ffffff,#d4d7d9,#898d90,#515252,#000000,#fe4500,#fea800,#fed634,#01a268,#7eed56,#2350a4,#3690ea,#51e9f4,#811f9f,#b44bc0,#ff99aa,#9c6925",
+ "defaultCanvas": "config/default-canvas-50.txt"
+ }
+ },
+ "epi-place": {
+ "metadata": {
+ "name": "epi/place",
+ "slug": "epi-place",
+ "description": "Le Roi de la malice est passé par là",
+ "canvasDimensions": 250,
+ "iconURL": "https://media.tenor.com/XUHq8pN_maQAAAAi/puffer-fish-fish.gif",
+ "isPublic": true
+ },
+ "settings": {
+ "roomColors": "#ffffff,#d4d7d9,#898d90,#515252,#6c001a,#be0039,#fe4500,#fea800,#fed634,#fff8b8,#01a268,#00cc78,#7eed56,#02756f,#019eaa,#00ccbf,#2350a4,#3690ea,#51e9f4,#493ac1,#6a5cff,#94b3ff,#811f9f,#b44bc0,#e4aaff,#de107f,#ff3981,#ff99aa,#6d482f,#9c6925,#ffb470,#000000",
+ "defaultCanvas": "config/default-canvas-250.txt"
+ }
+ },
+ "test": {
+ "metadata": {
+ "name": "Test Room",
+ "description": "A room small enough to test things out",
+ "canvasDimensions": 10,
+ "isPublic": true
+ },
+ "settings": {
+ "roomColors": "#ffffff,#d4d7d9,#898d90,#515252,#000000,#fe4500,#fea800,#fed634,#01a268,#7eed56,#2350a4,#3690ea,#51e9f4,#811f9f,#b44bc0,#ff99aa,#9c6925"
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/rushs/eplace/server/docker-compose.yml b/rushs/eplace/server/docker-compose.yml
new file mode 100644
index 0000000..f0419b9
--- /dev/null
+++ b/rushs/eplace/server/docker-compose.yml
@@ -0,0 +1,56 @@
+version: '3.9'
+services:
+ postgres:
+ image: registry.cri.epita.fr/ing/assistants/public/registry/postgres:15.2-alpine
+ container_name: postgres
+ restart: always
+ environment:
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: postgres
+ POSTGRES_DB: eplace
+ expose:
+ - 5432
+ volumes:
+ - postgres-data:/var/lib/postgresql/data
+ # Proper docker-compose would use named networks
+ # networks:
+ # - postgres-network
+ redis:
+ image: registry.cri.epita.fr/ing/assistants/public/registry/redis:7.0.9-alpine
+ container_name: redis
+ restart: always
+ expose:
+ - 6379
+ volumes:
+ - redis-data:/data
+ # Proper docker-compose would use named networks
+ # networks:
+ # - redis-network
+ eplace:
+ image: registry.cri.epita.fr/ing/assistants/public/registry/eplace:latest
+ container_name: eplace
+ restart: always
+ environment:
+ NODE_ENV: production
+ volumes:
+ - ./config:/usr/src/app/config
+ - type: 'bind'
+ source: './.env'
+ target: '/usr/src/app/.env'
+ ports:
+ - 3000:3000
+ - 3333:3333
+ # Proper docker-compose would use named networks
+ # networks:
+ # - postgres-network
+ # - redis-network
+ depends_on:
+ - postgres
+ - redis
+volumes:
+ postgres-data:
+ redis-data:
+ # Proper docker-compose would use named networks
+ # networks:
+ # postgres-network:
+ # redis-network:
diff --git a/rushs/eplace/server/openapi/openapi.json b/rushs/eplace/server/openapi/openapi.json
new file mode 100644
index 0000000..4f0dd77
--- /dev/null
+++ b/rushs/eplace/server/openapi/openapi.json
@@ -0,0 +1,5064 @@
+{
+ "openapi": "3.0.3",
+ "info": {
+ "title": "E/PLACE API",
+ "description": "Publicly available API for E/PLACE",
+ "version": "1.0.0"
+ },
+ "servers": [
+ {
+ "url": "http://localhost:3333/api"
+ }
+ ],
+ "paths": {
+ "/status": {
+ "get": {
+ "operationId": "status",
+ "summary": "Get the status of the API",
+ "description": "Get the status of the API",
+ "tags": [
+ "Misc"
+ ],
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/reload-config": {
+ "put": {
+ "operationId": "reloadConfig",
+ "summary": "Reload the config",
+ "description": "Reload the config",
+ "tags": [
+ "Admin"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "reloadLocally": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "reloadLocally"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/update-event/{slug}": {
+ "post": {
+ "operationId": "changeEvent",
+ "summary": "Update the event of a room",
+ "description": "Update the event of a room",
+ "tags": [
+ "Admin"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "event": {
+ "type": "string",
+ "enum": [
+ null,
+ "EVEN_OR_ODD",
+ "EVEN_OR_ODD_DEFAULT_CANVAS",
+ "INITIAL_DEFAULT_CANVAS",
+ "RANDOM",
+ "GROUPS",
+ "VOID"
+ ],
+ "nullable": true,
+ "default": null
+ },
+ "radius": {
+ "type": "number"
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "message"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/update-rate-limits/{slug}": {
+ "post": {
+ "operationId": "updateRateLimits",
+ "summary": "Update the rate limits",
+ "description": "Update the rate limits for the API",
+ "tags": [
+ "Admin"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "rateLimitName": {
+ "type": "string",
+ "enum": [
+ "testsLimiter",
+ "getCanvasLimiter",
+ "getPixelLimiter",
+ "placePixelLimiter",
+ "getRoomsLimiter",
+ "getRoomConfigLimiter",
+ "createRoomLimiter",
+ "updateRoomLimiter",
+ "deleteRoomLimiter",
+ "getStudentLimiter",
+ "updateStudentLimiter",
+ "sendMessageLimiter",
+ "reportRoomLimiter"
+ ]
+ },
+ "limit": {
+ "type": "number",
+ "minimum": 1
+ },
+ "interval": {
+ "type": "number",
+ "minimum": 0
+ }
+ },
+ "required": [
+ "rateLimitName",
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/tests/error": {
+ "get": {
+ "operationId": "tests-error",
+ "summary": "Return a server error",
+ "description": "Always return 500 Internal Server Error",
+ "tags": [
+ "Tests"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/tests/invalid-token": {
+ "post": {
+ "operationId": "tests-invalid-token",
+ "summary": "Return an invalid token error",
+ "description": "Always return 401 Unauthorized \"Invalid token\"",
+ "tags": [
+ "Tests"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {},
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/tests/expired-token": {
+ "post": {
+ "operationId": "tests-expired-token",
+ "summary": "Return a token expired error",
+ "description": "Always return 401 Unauthorized \"Token expired\"",
+ "tags": [
+ "Tests"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {},
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/tests/too-many-requests": {
+ "get": {
+ "operationId": "tests-too-many-requests",
+ "summary": "Return a too many requests error",
+ "description": "Always return 429 Too Many Requests",
+ "tags": [
+ "Tests"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/students": {
+ "get": {
+ "operationId": "students-getStudents",
+ "summary": "Get all students",
+ "description": "Get all students",
+ "tags": [
+ "Admin"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "type": "number"
+ },
+ "login": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "uid",
+ "login"
+ ],
+ "additionalProperties": false
+ },
+ "description": "An array of students with their UID and login"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/students/{id}": {
+ "get": {
+ "operationId": "students-getStudent",
+ "summary": "Get a student by UID or login",
+ "description": "Get a student by UID or login",
+ "tags": [
+ "Students (Mandatory)"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The UID or login of the student"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "groups": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "ADMIN",
+ "YAKA",
+ "ING1_LYON",
+ "ING1_PARIS",
+ "ING1_RENNES",
+ "ING1_STRASBOURG",
+ "ING1_TOULOUSE"
+ ]
+ }
+ },
+ "uid": {
+ "type": "number"
+ },
+ "login": {
+ "type": "string"
+ },
+ "avatarURL": {
+ "type": "string",
+ "nullable": true
+ },
+ "quote": {
+ "type": "string",
+ "nullable": true
+ },
+ "currentRoomSlug": {
+ "type": "string",
+ "nullable": true
+ },
+ "banUntil": {
+ "type": "string",
+ "format": "date-time",
+ "nullable": true
+ }
+ },
+ "required": [
+ "groups",
+ "uid",
+ "login",
+ "avatarURL",
+ "quote",
+ "currentRoomSlug",
+ "banUntil"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "operationId": "students-updateStudent",
+ "summary": "Update a student by UID or login",
+ "description": "Update a student by UID or login",
+ "tags": [
+ "Students (Optional)"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "avatarURL": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": [
+ "null"
+ ],
+ "nullable": true
+ }
+ ],
+ "description": "The URL of your avatar"
+ },
+ "quote": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": [
+ "null"
+ ],
+ "nullable": true
+ }
+ ],
+ "description": "Your quote"
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "Your student UID or login"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "groups": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "ADMIN",
+ "YAKA",
+ "ING1_LYON",
+ "ING1_PARIS",
+ "ING1_RENNES",
+ "ING1_STRASBOURG",
+ "ING1_TOULOUSE"
+ ]
+ }
+ },
+ "uid": {
+ "type": "number"
+ },
+ "login": {
+ "type": "string"
+ },
+ "avatarURL": {
+ "type": "string",
+ "nullable": true
+ },
+ "quote": {
+ "type": "string",
+ "nullable": true
+ },
+ "currentRoomSlug": {
+ "type": "string",
+ "nullable": true
+ },
+ "banUntil": {
+ "type": "string",
+ "format": "date-time",
+ "nullable": true
+ }
+ },
+ "required": [
+ "groups",
+ "uid",
+ "login",
+ "avatarURL",
+ "quote",
+ "currentRoomSlug",
+ "banUntil"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/students/{id}/ban": {
+ "post": {
+ "operationId": "students-banStudent",
+ "summary": "Ban a student by UID or login",
+ "description": "Ban a student by UID or by login. If no date is provided, the student will be unbanned.",
+ "tags": [
+ "Admin"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "banUntil": {
+ "type": "string",
+ "description": "The date until the student is banned"
+ },
+ "reason": {
+ "type": "string",
+ "description": "The reason of the ban"
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The UID or login of the student"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "groups": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "ADMIN",
+ "YAKA",
+ "ING1_LYON",
+ "ING1_PARIS",
+ "ING1_RENNES",
+ "ING1_STRASBOURG",
+ "ING1_TOULOUSE"
+ ]
+ }
+ },
+ "uid": {
+ "type": "number"
+ },
+ "login": {
+ "type": "string"
+ },
+ "avatarURL": {
+ "type": "string",
+ "nullable": true
+ },
+ "quote": {
+ "type": "string",
+ "nullable": true
+ },
+ "currentRoomSlug": {
+ "type": "string",
+ "nullable": true
+ },
+ "banUntil": {
+ "type": "string",
+ "format": "date-time",
+ "nullable": true
+ }
+ },
+ "required": [
+ "groups",
+ "uid",
+ "login",
+ "avatarURL",
+ "quote",
+ "currentRoomSlug",
+ "banUntil"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/rooms": {
+ "get": {
+ "operationId": "rooms-getRooms",
+ "summary": "Get all rooms",
+ "description": "List all the rooms available to the student",
+ "tags": [
+ "Rooms (Optional)"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "List of available rooms",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Room"
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "rooms-createRoom",
+ "summary": "Create a room",
+ "description": "Create a new room",
+ "tags": [
+ "Rooms (Optional)"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the room"
+ },
+ "description": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": [
+ "null"
+ ],
+ "nullable": true
+ }
+ ],
+ "description": "The description of the room"
+ },
+ "iconURL": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": [
+ "null"
+ ],
+ "nullable": true
+ }
+ ],
+ "description": "The URL of the room's icon"
+ },
+ "isPublic": {
+ "type": "boolean",
+ "description": "Whether the room is public or not. Defaults to false"
+ },
+ "studentsWhitelist": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "number"
+ }
+ ]
+ },
+ "description": "The list of students allowed to join the room. Effective only if isPublic is false. Accepts both UIDs and logins. Defaults to an empty array"
+ },
+ "studentsBlacklist": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "number"
+ }
+ ]
+ },
+ "description": "The list of students not allowed to join the room. Effective only if isPublic is true. Accepts both UIDs and logins. Defaults to an empty array"
+ }
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "slug": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true
+ },
+ "iconURL": {
+ "type": "string",
+ "nullable": true
+ },
+ "canvasDimensions": {
+ "type": "number"
+ },
+ "isPublic": {
+ "type": "boolean"
+ },
+ "studentsWhitelist": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "studentsBlacklist": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "ownerUid": {
+ "type": "number"
+ },
+ "password": {
+ "type": "string",
+ "nullable": true
+ },
+ "hidden": {
+ "type": "boolean"
+ },
+ "deleted": {
+ "type": "boolean"
+ },
+ "createdAt": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "required": [
+ "slug",
+ "name",
+ "description",
+ "iconURL",
+ "canvasDimensions",
+ "isPublic",
+ "studentsWhitelist",
+ "studentsBlacklist",
+ "ownerUid",
+ "password",
+ "hidden",
+ "deleted",
+ "createdAt"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/rooms/{slug}": {
+ "put": {
+ "operationId": "rooms-updateRoom",
+ "summary": "Update a room",
+ "description": "Update a room",
+ "tags": [
+ "Rooms (Optional)"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the room"
+ },
+ "description": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": [
+ "null"
+ ],
+ "nullable": true
+ }
+ ],
+ "description": "The description of the room"
+ },
+ "iconURL": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": [
+ "null"
+ ],
+ "nullable": true
+ }
+ ],
+ "description": "The URL of the room's icon"
+ },
+ "isPublic": {
+ "type": "boolean",
+ "description": "Whether the room is public or not. Defaults to false"
+ },
+ "studentsWhitelist": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "number"
+ }
+ ]
+ },
+ "description": "The list of students allowed to join the room. Effective only if isPublic is false. Accepts both UIDs and logins. Defaults to an empty array"
+ },
+ "studentsBlacklist": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "number"
+ }
+ ]
+ },
+ "description": "The list of students not allowed to join the room. Effective only if isPublic is true. Accepts both UIDs and logins. Defaults to an empty array"
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The slug of the room"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "slug": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true
+ },
+ "iconURL": {
+ "type": "string",
+ "nullable": true
+ },
+ "canvasDimensions": {
+ "type": "number"
+ },
+ "isPublic": {
+ "type": "boolean"
+ },
+ "studentsWhitelist": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "studentsBlacklist": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "ownerUid": {
+ "type": "number"
+ },
+ "password": {
+ "type": "string",
+ "nullable": true
+ },
+ "hidden": {
+ "type": "boolean"
+ },
+ "deleted": {
+ "type": "boolean"
+ },
+ "createdAt": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "required": [
+ "slug",
+ "name",
+ "description",
+ "iconURL",
+ "canvasDimensions",
+ "isPublic",
+ "studentsWhitelist",
+ "studentsBlacklist",
+ "ownerUid",
+ "password",
+ "hidden",
+ "deleted",
+ "createdAt"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "operationId": "rooms-deleteRoom",
+ "summary": "Delete a room",
+ "description": "Delete a room",
+ "tags": [
+ "Rooms (Optional)"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The slug of the room"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "boolean"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/rooms/{slug}/config": {
+ "get": {
+ "operationId": "rooms-getRoomConfig",
+ "summary": "Get the room config",
+ "description": "Get the room config",
+ "tags": [
+ "Rooms (Mandatory)"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The slug of the room"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "metadata": {
+ "type": "object",
+ "properties": {
+ "slug": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": [
+ "null"
+ ],
+ "nullable": true
+ }
+ ]
+ },
+ "iconURL": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": [
+ "null"
+ ],
+ "nullable": true
+ }
+ ]
+ },
+ "canvasDimensions": {
+ "type": "number"
+ },
+ "isPublic": {
+ "type": "boolean"
+ },
+ "studentsWhitelist": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "studentsBlacklist": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "ownerUid": {
+ "type": "number"
+ },
+ "createdAt": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "required": [
+ "slug",
+ "name",
+ "description",
+ "iconURL",
+ "canvasDimensions",
+ "isPublic",
+ "ownerUid",
+ "createdAt"
+ ],
+ "additionalProperties": false
+ },
+ "settings": {
+ "type": "object",
+ "properties": {
+ "roomColors": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "roomColors"
+ ],
+ "additionalProperties": false
+ },
+ "rateLimits": {
+ "type": "object",
+ "properties": {
+ "testsLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "getCanvasLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "getPixelLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "placePixelLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "getRoomsLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "getRoomConfigLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "createRoomLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "updateRoomLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "deleteRoomLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "getStudentLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "updateStudentLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "sendMessageLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "reportRoomLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "required": [
+ "testsLimiter",
+ "getCanvasLimiter",
+ "getPixelLimiter",
+ "placePixelLimiter",
+ "getRoomsLimiter",
+ "getRoomConfigLimiter",
+ "createRoomLimiter",
+ "updateRoomLimiter",
+ "deleteRoomLimiter",
+ "getStudentLimiter",
+ "updateStudentLimiter",
+ "sendMessageLimiter",
+ "reportRoomLimiter"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "required": [
+ "metadata",
+ "settings",
+ "rateLimits"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "rooms-changeRoomConfig",
+ "summary": "Load another json room config",
+ "description": "Load another json room config",
+ "tags": [
+ "Admin"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "settings": {
+ "type": "object",
+ "properties": {
+ "roomColors": {
+ "type": "string",
+ "description": "The colors of the room"
+ }
+ },
+ "additionalProperties": false,
+ "description": "The settings to change"
+ },
+ "events": {
+ "type": "object",
+ "properties": {
+ "colorationEvent": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of the coloration event"
+ },
+ "groups": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "The groups of the coloration event"
+ },
+ "colorsSubSet": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ },
+ "description": "The colors subset of the coloration event"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "additionalProperties": false
+ },
+ "radiusEvent": {
+ "type": "object",
+ "properties": {
+ "radius": {
+ "type": "number",
+ "description": "The radius of the event"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ },
+ "rateLimitsOverride": {
+ "type": "object",
+ "properties": {
+ "testsLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "getCanvasLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "getPixelLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "placePixelLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "getRoomsLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "getRoomConfigLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "createRoomLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "updateRoomLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "deleteRoomLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "getStudentLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "updateStudentLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "sendMessageLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ },
+ "reportRoomLimiter": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "number"
+ },
+ "interval": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "limit",
+ "interval"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "required": [
+ "testsLimiter",
+ "getCanvasLimiter",
+ "getPixelLimiter",
+ "placePixelLimiter",
+ "getRoomsLimiter",
+ "getRoomConfigLimiter",
+ "createRoomLimiter",
+ "updateRoomLimiter",
+ "deleteRoomLimiter",
+ "getStudentLimiter",
+ "updateStudentLimiter",
+ "sendMessageLimiter",
+ "reportRoomLimiter"
+ ],
+ "additionalProperties": false,
+ "description": "The rate limits to override"
+ }
+ },
+ "required": [
+ "events"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The slug of the room"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "boolean"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/rooms/{slug}/report": {
+ "post": {
+ "operationId": "rooms-reportRoom",
+ "summary": "Report a room",
+ "description": "Report a room",
+ "tags": [
+ "Misc"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "reason": {
+ "type": "string",
+ "description": "The reason for the report"
+ }
+ },
+ "required": [
+ "reason"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The slug of the room"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "boolean"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/rooms/yeet": {
+ "post": {
+ "operationId": "rooms-yeetFromRoom",
+ "summary": "Yeet a student from a room",
+ "description": "Yeet a student from a room",
+ "tags": [
+ "Admin"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "slug": {
+ "type": "string",
+ "description": "The slug of the room. If empty, all rooms will be yeeted"
+ },
+ "studentsList": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "number"
+ }
+ ]
+ },
+ "description": "The list of students to yeet. If empty, all students will be yeeted"
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "boolean"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/rooms/{slug}/canvas": {
+ "get": {
+ "operationId": "rooms-canvas-getCanvas",
+ "summary": "Get the canvas of a room",
+ "description": "Get the canvas of a room",
+ "tags": [
+ "Rooms (Mandatory)"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The slug of the room"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "pixels": {
+ "type": "string",
+ "description": "The pixels of the room"
+ }
+ },
+ "required": [
+ "pixels"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/rooms/{slug}/canvas/pixels": {
+ "get": {
+ "operationId": "rooms-canvas-getPixel",
+ "summary": "Get the pixels of a room",
+ "description": "Get the pixels of a room",
+ "tags": [
+ "Rooms (Mandatory)"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The slug of the room"
+ },
+ {
+ "name": "posX",
+ "in": "query",
+ "required": true,
+ "schema": {
+ "type": "number"
+ },
+ "description": "The X position of the pixel"
+ },
+ {
+ "name": "posY",
+ "in": "query",
+ "required": true,
+ "schema": {
+ "type": "number"
+ },
+ "description": "The Y position of the pixel"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "roomSlug": {
+ "type": "string"
+ },
+ "posX": {
+ "type": "number"
+ },
+ "posY": {
+ "type": "number"
+ },
+ "color": {
+ "type": "number"
+ },
+ "timestamp": {
+ "anyOf": [
+ {
+ "type": "number"
+ },
+ {
+ "enum": [
+ "null"
+ ],
+ "nullable": true
+ }
+ ]
+ },
+ "placedByUid": {
+ "anyOf": [
+ {
+ "type": "number"
+ },
+ {
+ "enum": [
+ "null"
+ ],
+ "nullable": true
+ }
+ ]
+ }
+ },
+ "required": [
+ "roomSlug",
+ "posX",
+ "posY",
+ "color",
+ "timestamp",
+ "placedByUid"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "rooms-canvas-placePixel",
+ "summary": "Place a pixel in a room",
+ "description": "Place a pixel in a room",
+ "tags": [
+ "Rooms (Mandatory)"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "posX": {
+ "type": "number",
+ "description": "The X position of the pixel"
+ },
+ "posY": {
+ "type": "number",
+ "description": "The Y position of the pixel"
+ },
+ "color": {
+ "type": "number",
+ "description": "The color index of the pixel"
+ }
+ },
+ "required": [
+ "posX",
+ "posY",
+ "color"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The slug of the room"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "roomSlug": {
+ "type": "string"
+ },
+ "posX": {
+ "type": "number"
+ },
+ "posY": {
+ "type": "number"
+ },
+ "color": {
+ "type": "number"
+ },
+ "timestamp": {
+ "anyOf": [
+ {
+ "type": "number"
+ },
+ {
+ "enum": [
+ "null"
+ ],
+ "nullable": true
+ }
+ ]
+ },
+ "placedByUid": {
+ "anyOf": [
+ {
+ "type": "number"
+ },
+ {
+ "enum": [
+ "null"
+ ],
+ "nullable": true
+ }
+ ]
+ }
+ },
+ "required": [
+ "roomSlug",
+ "posX",
+ "posY",
+ "color",
+ "timestamp",
+ "placedByUid"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/rooms/{slug}/canvas/resize": {
+ "put": {
+ "operationId": "rooms-canvas-resizeCanvas",
+ "summary": "Resize the canvas of a room",
+ "description": "Resize the canvas of a room",
+ "tags": [
+ "Admin"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "newCanvasDimensions": {
+ "type": "number",
+ "description": "The new size of the room"
+ }
+ },
+ "required": [
+ "newCanvasDimensions"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The slug of the room"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "slug": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true
+ },
+ "iconURL": {
+ "type": "string",
+ "nullable": true
+ },
+ "canvasDimensions": {
+ "type": "number"
+ },
+ "isPublic": {
+ "type": "boolean"
+ },
+ "studentsWhitelist": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "studentsBlacklist": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "ownerUid": {
+ "type": "number"
+ },
+ "password": {
+ "type": "string",
+ "nullable": true
+ },
+ "hidden": {
+ "type": "boolean"
+ },
+ "deleted": {
+ "type": "boolean"
+ },
+ "createdAt": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "required": [
+ "slug",
+ "name",
+ "description",
+ "iconURL",
+ "canvasDimensions",
+ "isPublic",
+ "studentsWhitelist",
+ "studentsBlacklist",
+ "ownerUid",
+ "password",
+ "hidden",
+ "deleted",
+ "createdAt"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/rooms/{slug}/canvas/reset": {
+ "put": {
+ "operationId": "rooms-canvas-resetCanvas",
+ "summary": "Reset the canvas of a room",
+ "description": "Reset the canvas of a room",
+ "tags": [
+ "Admin"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "resetOnDefault": {
+ "type": "boolean",
+ "description": "Reset the canvas on the default image if exists"
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The slug of the room"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "slug": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true
+ },
+ "iconURL": {
+ "type": "string",
+ "nullable": true
+ },
+ "canvasDimensions": {
+ "type": "number"
+ },
+ "isPublic": {
+ "type": "boolean"
+ },
+ "studentsWhitelist": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "studentsBlacklist": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "ownerUid": {
+ "type": "number"
+ },
+ "password": {
+ "type": "string",
+ "nullable": true
+ },
+ "hidden": {
+ "type": "boolean"
+ },
+ "deleted": {
+ "type": "boolean"
+ },
+ "createdAt": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "required": [
+ "slug",
+ "name",
+ "description",
+ "iconURL",
+ "canvasDimensions",
+ "isPublic",
+ "studentsWhitelist",
+ "studentsBlacklist",
+ "ownerUid",
+ "password",
+ "hidden",
+ "deleted",
+ "createdAt"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/rooms/{slug}/canvas/load": {
+ "post": {
+ "operationId": "rooms-canvas-loadCanvas",
+ "summary": "Load the canvas of a room",
+ "description": "Load the canvas of a room",
+ "tags": [
+ "Admin"
+ ],
+ "security": [
+ {
+ "Authorization": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "backupId": {
+ "type": "number",
+ "description": "The id of the backup"
+ }
+ },
+ "required": [
+ "backupId"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "The slug of the room"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "boolean"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InvalidToken": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Invalid token"
+ }
+ },
+ "TokenExpired": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Token expired"
+ }
+ },
+ "Unauthenticated": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "Unauthenticated"
+ }
+ },
+ "Banned": {
+ "value": {
+ "code": "UNAUTHORIZED",
+ "message": "You are banned"
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "NotAdmin": {
+ "value": {
+ "code": "FORBIDDEN",
+ "message": "You are not an admin"
+ }
+ }
+ }
+ }
+ }
+ },
+ "429": {
+ "description": "Too Many Requests",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "TooManyRequests": {
+ "value": {
+ "code": "TOO_MANY_REQUESTS",
+ "message": "Too many requests"
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ },
+ "examples": {
+ "InternalServerError": {
+ "value": {
+ "code": "INTERNAL_SERVER_ERROR",
+ "message": "An error occured"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "securitySchemes": {
+ "Authorization": {
+ "type": "http",
+ "scheme": "bearer"
+ }
+ },
+ "responses": {
+ "error": {
+ "description": "Error response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
+ },
+ "code": {
+ "type": "string"
+ },
+ "issues": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "message"
+ ],
+ "additionalProperties": false
+ }
+ }
+ },
+ "required": [
+ "message",
+ "code"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ }
+ },
+ "schemas": {
+ "Room": {
+ "type": "object",
+ "properties": {
+ "slug": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true
+ },
+ "iconURL": {
+ "type": "string",
+ "nullable": true
+ },
+ "canvasDimensions": {
+ "type": "number"
+ },
+ "isPublic": {
+ "type": "boolean"
+ },
+ "studentsWhitelist": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "studentsBlacklist": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "ownerUid": {
+ "type": "number"
+ },
+ "password": {
+ "type": "string",
+ "nullable": true
+ },
+ "hidden": {
+ "type": "boolean"
+ },
+ "deleted": {
+ "type": "boolean"
+ },
+ "createdAt": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ },
+ "Student": {
+ "type": "object",
+ "properties": {
+ "groups": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "ADMIN",
+ "YAKA",
+ "ING1_LYON",
+ "ING1_PARIS",
+ "ING1_RENNES",
+ "ING1_STRASBOURG",
+ "ING1_TOULOUSE"
+ ]
+ }
+ },
+ "uid": {
+ "type": "number"
+ },
+ "login": {
+ "type": "string"
+ },
+ "avatarURL": {
+ "type": "string",
+ "nullable": true
+ },
+ "quote": {
+ "type": "string",
+ "nullable": true
+ },
+ "currentRoomSlug": {
+ "type": "string",
+ "nullable": true
+ },
+ "banUntil": {
+ "type": "string",
+ "format": "date-time",
+ "nullable": true
+ }
+ }
+ },
+ "Error": {
+ "type": "object",
+ "properties": {
+ "code": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ {
+ "name": "Misc"
+ },
+ {
+ "name": "Tests"
+ },
+ {
+ "name": "Rooms (Mandatory)"
+ },
+ {
+ "name": "Rooms (Optional)"
+ },
+ {
+ "name": "Students (Mandatory)"
+ },
+ {
+ "name": "Students (Optional)"
+ },
+ {
+ "name": "Admin"
+ }
+ ]
+} \ No newline at end of file