feat(user): added description and global guest user mute

This commit is contained in:
Maieul BOYER 2025-12-18 14:46:02 +01:00 committed by Maix0
parent bcba86ed8a
commit 556138d624
24 changed files with 1856 additions and 1460 deletions

242
frontend/pnpm-lock.yaml generated
View file

@ -10,7 +10,7 @@ importers:
dependencies: dependencies:
'@tailwindcss/vite': '@tailwindcss/vite':
specifier: ^4.1.18 specifier: ^4.1.18
version: 4.1.18(vite@7.3.0(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)) version: 4.1.18(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2))
'@types/qrcode': '@types/qrcode':
specifier: ^1.5.6 specifier: ^1.5.6
version: 1.5.6 version: 1.5.6
@ -35,165 +35,165 @@ importers:
version: 5.9.3 version: 5.9.3
vite: vite:
specifier: ^7.3.0 specifier: ^7.3.0
version: 7.3.0(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2) version: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)
vite-tsconfig-paths: vite-tsconfig-paths:
specifier: ^5.1.4 specifier: ^5.1.4
version: 5.1.4(typescript@5.9.3)(vite@7.3.0(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)) version: 5.1.4(typescript@5.9.3)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2))
packages: packages:
'@esbuild/aix-ppc64@0.27.1': '@esbuild/aix-ppc64@0.27.2':
resolution: {integrity: sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==} resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [ppc64] cpu: [ppc64]
os: [aix] os: [aix]
'@esbuild/android-arm64@0.27.1': '@esbuild/android-arm64@0.27.2':
resolution: {integrity: sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==} resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@esbuild/android-arm@0.27.1': '@esbuild/android-arm@0.27.2':
resolution: {integrity: sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==} resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm] cpu: [arm]
os: [android] os: [android]
'@esbuild/android-x64@0.27.1': '@esbuild/android-x64@0.27.2':
resolution: {integrity: sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==} resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [android] os: [android]
'@esbuild/darwin-arm64@0.27.1': '@esbuild/darwin-arm64@0.27.2':
resolution: {integrity: sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==} resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@esbuild/darwin-x64@0.27.1': '@esbuild/darwin-x64@0.27.2':
resolution: {integrity: sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==} resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@esbuild/freebsd-arm64@0.27.1': '@esbuild/freebsd-arm64@0.27.2':
resolution: {integrity: sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==} resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [freebsd] os: [freebsd]
'@esbuild/freebsd-x64@0.27.1': '@esbuild/freebsd-x64@0.27.2':
resolution: {integrity: sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==} resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@esbuild/linux-arm64@0.27.1': '@esbuild/linux-arm64@0.27.2':
resolution: {integrity: sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==} resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@esbuild/linux-arm@0.27.1': '@esbuild/linux-arm@0.27.2':
resolution: {integrity: sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==} resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@esbuild/linux-ia32@0.27.1': '@esbuild/linux-ia32@0.27.2':
resolution: {integrity: sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==} resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [ia32] cpu: [ia32]
os: [linux] os: [linux]
'@esbuild/linux-loong64@0.27.1': '@esbuild/linux-loong64@0.27.2':
resolution: {integrity: sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==} resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [loong64] cpu: [loong64]
os: [linux] os: [linux]
'@esbuild/linux-mips64el@0.27.1': '@esbuild/linux-mips64el@0.27.2':
resolution: {integrity: sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==} resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [mips64el] cpu: [mips64el]
os: [linux] os: [linux]
'@esbuild/linux-ppc64@0.27.1': '@esbuild/linux-ppc64@0.27.2':
resolution: {integrity: sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==} resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
'@esbuild/linux-riscv64@0.27.1': '@esbuild/linux-riscv64@0.27.2':
resolution: {integrity: sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==} resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
'@esbuild/linux-s390x@0.27.1': '@esbuild/linux-s390x@0.27.2':
resolution: {integrity: sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==} resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
'@esbuild/linux-x64@0.27.1': '@esbuild/linux-x64@0.27.2':
resolution: {integrity: sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==} resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@esbuild/netbsd-arm64@0.27.1': '@esbuild/netbsd-arm64@0.27.2':
resolution: {integrity: sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==} resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [netbsd] os: [netbsd]
'@esbuild/netbsd-x64@0.27.1': '@esbuild/netbsd-x64@0.27.2':
resolution: {integrity: sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==} resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [netbsd] os: [netbsd]
'@esbuild/openbsd-arm64@0.27.1': '@esbuild/openbsd-arm64@0.27.2':
resolution: {integrity: sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==} resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [openbsd] os: [openbsd]
'@esbuild/openbsd-x64@0.27.1': '@esbuild/openbsd-x64@0.27.2':
resolution: {integrity: sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==} resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [openbsd] os: [openbsd]
'@esbuild/openharmony-arm64@0.27.1': '@esbuild/openharmony-arm64@0.27.2':
resolution: {integrity: sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==} resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [openharmony] os: [openharmony]
'@esbuild/sunos-x64@0.27.1': '@esbuild/sunos-x64@0.27.2':
resolution: {integrity: sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==} resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [sunos] os: [sunos]
'@esbuild/win32-arm64@0.27.1': '@esbuild/win32-arm64@0.27.2':
resolution: {integrity: sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==} resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@esbuild/win32-ia32@0.27.1': '@esbuild/win32-ia32@0.27.2':
resolution: {integrity: sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==} resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
'@esbuild/win32-x64@0.27.1': '@esbuild/win32-x64@0.27.2':
resolution: {integrity: sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==} resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
@ -423,8 +423,8 @@ packages:
'@types/js-cookie@3.0.6': '@types/js-cookie@3.0.6':
resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==}
'@types/node@25.0.2': '@types/node@25.0.3':
resolution: {integrity: sha512-gWEkeiyYE4vqjON/+Obqcoeffmk0NF15WSBwSs7zwVA2bAbTaE0SJ7P0WNGoJn8uE7fiaV5a7dKYIJriEqOrmA==} resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==}
'@types/qrcode@1.5.6': '@types/qrcode@1.5.6':
resolution: {integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==} resolution: {integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==}
@ -494,8 +494,8 @@ packages:
resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==}
engines: {node: '>=10.13.0'} engines: {node: '>=10.13.0'}
esbuild@0.27.1: esbuild@0.27.2:
resolution: {integrity: sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==} resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==}
engines: {node: '>=18'} engines: {node: '>=18'}
hasBin: true hasBin: true
@ -808,82 +808,82 @@ packages:
snapshots: snapshots:
'@esbuild/aix-ppc64@0.27.1': '@esbuild/aix-ppc64@0.27.2':
optional: true optional: true
'@esbuild/android-arm64@0.27.1': '@esbuild/android-arm64@0.27.2':
optional: true optional: true
'@esbuild/android-arm@0.27.1': '@esbuild/android-arm@0.27.2':
optional: true optional: true
'@esbuild/android-x64@0.27.1': '@esbuild/android-x64@0.27.2':
optional: true optional: true
'@esbuild/darwin-arm64@0.27.1': '@esbuild/darwin-arm64@0.27.2':
optional: true optional: true
'@esbuild/darwin-x64@0.27.1': '@esbuild/darwin-x64@0.27.2':
optional: true optional: true
'@esbuild/freebsd-arm64@0.27.1': '@esbuild/freebsd-arm64@0.27.2':
optional: true optional: true
'@esbuild/freebsd-x64@0.27.1': '@esbuild/freebsd-x64@0.27.2':
optional: true optional: true
'@esbuild/linux-arm64@0.27.1': '@esbuild/linux-arm64@0.27.2':
optional: true optional: true
'@esbuild/linux-arm@0.27.1': '@esbuild/linux-arm@0.27.2':
optional: true optional: true
'@esbuild/linux-ia32@0.27.1': '@esbuild/linux-ia32@0.27.2':
optional: true optional: true
'@esbuild/linux-loong64@0.27.1': '@esbuild/linux-loong64@0.27.2':
optional: true optional: true
'@esbuild/linux-mips64el@0.27.1': '@esbuild/linux-mips64el@0.27.2':
optional: true optional: true
'@esbuild/linux-ppc64@0.27.1': '@esbuild/linux-ppc64@0.27.2':
optional: true optional: true
'@esbuild/linux-riscv64@0.27.1': '@esbuild/linux-riscv64@0.27.2':
optional: true optional: true
'@esbuild/linux-s390x@0.27.1': '@esbuild/linux-s390x@0.27.2':
optional: true optional: true
'@esbuild/linux-x64@0.27.1': '@esbuild/linux-x64@0.27.2':
optional: true optional: true
'@esbuild/netbsd-arm64@0.27.1': '@esbuild/netbsd-arm64@0.27.2':
optional: true optional: true
'@esbuild/netbsd-x64@0.27.1': '@esbuild/netbsd-x64@0.27.2':
optional: true optional: true
'@esbuild/openbsd-arm64@0.27.1': '@esbuild/openbsd-arm64@0.27.2':
optional: true optional: true
'@esbuild/openbsd-x64@0.27.1': '@esbuild/openbsd-x64@0.27.2':
optional: true optional: true
'@esbuild/openharmony-arm64@0.27.1': '@esbuild/openharmony-arm64@0.27.2':
optional: true optional: true
'@esbuild/sunos-x64@0.27.1': '@esbuild/sunos-x64@0.27.2':
optional: true optional: true
'@esbuild/win32-arm64@0.27.1': '@esbuild/win32-arm64@0.27.2':
optional: true optional: true
'@esbuild/win32-ia32@0.27.1': '@esbuild/win32-ia32@0.27.2':
optional: true optional: true
'@esbuild/win32-x64@0.27.1': '@esbuild/win32-x64@0.27.2':
optional: true optional: true
'@jridgewell/gen-mapping@0.3.13': '@jridgewell/gen-mapping@0.3.13':
@ -1034,24 +1034,24 @@ snapshots:
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18
'@tailwindcss/oxide-win32-x64-msvc': 4.1.18 '@tailwindcss/oxide-win32-x64-msvc': 4.1.18
'@tailwindcss/vite@4.1.18(vite@7.3.0(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2))': '@tailwindcss/vite@4.1.18(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2))':
dependencies: dependencies:
'@tailwindcss/node': 4.1.18 '@tailwindcss/node': 4.1.18
'@tailwindcss/oxide': 4.1.18 '@tailwindcss/oxide': 4.1.18
tailwindcss: 4.1.18 tailwindcss: 4.1.18
vite: 7.3.0(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2) vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)
'@types/estree@1.0.8': {} '@types/estree@1.0.8': {}
'@types/js-cookie@3.0.6': {} '@types/js-cookie@3.0.6': {}
'@types/node@25.0.2': '@types/node@25.0.3':
dependencies: dependencies:
undici-types: 7.16.0 undici-types: 7.16.0
'@types/qrcode@1.5.6': '@types/qrcode@1.5.6':
dependencies: dependencies:
'@types/node': 25.0.2 '@types/node': 25.0.3
ansi-regex@5.0.1: {} ansi-regex@5.0.1: {}
@ -1108,34 +1108,34 @@ snapshots:
graceful-fs: 4.2.11 graceful-fs: 4.2.11
tapable: 2.3.0 tapable: 2.3.0
esbuild@0.27.1: esbuild@0.27.2:
optionalDependencies: optionalDependencies:
'@esbuild/aix-ppc64': 0.27.1 '@esbuild/aix-ppc64': 0.27.2
'@esbuild/android-arm': 0.27.1 '@esbuild/android-arm': 0.27.2
'@esbuild/android-arm64': 0.27.1 '@esbuild/android-arm64': 0.27.2
'@esbuild/android-x64': 0.27.1 '@esbuild/android-x64': 0.27.2
'@esbuild/darwin-arm64': 0.27.1 '@esbuild/darwin-arm64': 0.27.2
'@esbuild/darwin-x64': 0.27.1 '@esbuild/darwin-x64': 0.27.2
'@esbuild/freebsd-arm64': 0.27.1 '@esbuild/freebsd-arm64': 0.27.2
'@esbuild/freebsd-x64': 0.27.1 '@esbuild/freebsd-x64': 0.27.2
'@esbuild/linux-arm': 0.27.1 '@esbuild/linux-arm': 0.27.2
'@esbuild/linux-arm64': 0.27.1 '@esbuild/linux-arm64': 0.27.2
'@esbuild/linux-ia32': 0.27.1 '@esbuild/linux-ia32': 0.27.2
'@esbuild/linux-loong64': 0.27.1 '@esbuild/linux-loong64': 0.27.2
'@esbuild/linux-mips64el': 0.27.1 '@esbuild/linux-mips64el': 0.27.2
'@esbuild/linux-ppc64': 0.27.1 '@esbuild/linux-ppc64': 0.27.2
'@esbuild/linux-riscv64': 0.27.1 '@esbuild/linux-riscv64': 0.27.2
'@esbuild/linux-s390x': 0.27.1 '@esbuild/linux-s390x': 0.27.2
'@esbuild/linux-x64': 0.27.1 '@esbuild/linux-x64': 0.27.2
'@esbuild/netbsd-arm64': 0.27.1 '@esbuild/netbsd-arm64': 0.27.2
'@esbuild/netbsd-x64': 0.27.1 '@esbuild/netbsd-x64': 0.27.2
'@esbuild/openbsd-arm64': 0.27.1 '@esbuild/openbsd-arm64': 0.27.2
'@esbuild/openbsd-x64': 0.27.1 '@esbuild/openbsd-x64': 0.27.2
'@esbuild/openharmony-arm64': 0.27.1 '@esbuild/openharmony-arm64': 0.27.2
'@esbuild/sunos-x64': 0.27.1 '@esbuild/sunos-x64': 0.27.2
'@esbuild/win32-arm64': 0.27.1 '@esbuild/win32-arm64': 0.27.2
'@esbuild/win32-ia32': 0.27.1 '@esbuild/win32-ia32': 0.27.2
'@esbuild/win32-x64': 0.27.1 '@esbuild/win32-x64': 0.27.2
fdir@6.5.0(picomatch@4.0.3): fdir@6.5.0(picomatch@4.0.3):
optionalDependencies: optionalDependencies:
@ -1333,27 +1333,27 @@ snapshots:
undici-types@7.16.0: {} undici-types@7.16.0: {}
vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.3.0(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)): vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)):
dependencies: dependencies:
debug: 4.4.3 debug: 4.4.3
globrex: 0.1.2 globrex: 0.1.2
tsconfck: 3.1.6(typescript@5.9.3) tsconfck: 3.1.6(typescript@5.9.3)
optionalDependencies: optionalDependencies:
vite: 7.3.0(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2) vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
- typescript - typescript
vite@7.3.0(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2): vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2):
dependencies: dependencies:
esbuild: 0.27.1 esbuild: 0.27.2
fdir: 6.5.0(picomatch@4.0.3) fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3 picomatch: 4.0.3
postcss: 8.5.6 postcss: 8.5.6
rollup: 4.53.5 rollup: 4.53.5
tinyglobby: 0.2.15 tinyglobby: 0.2.15
optionalDependencies: optionalDependencies:
'@types/node': 25.0.2 '@types/node': 25.0.3
fsevents: 2.3.3 fsevents: 2.3.3
jiti: 2.6.1 jiti: 2.6.1
lightningcss: 1.30.2 lightningcss: 1.30.2

View file

@ -1,6 +1,12 @@
apis/OpenapiOtherApi.ts apis/OpenapiOtherApi.ts
apis/index.ts apis/index.ts
index.ts index.ts
models/AllowGuestMessage200Response.ts
models/AllowGuestMessage403Response.ts
models/ChangeDesc200Response.ts
models/ChangeDesc400Response.ts
models/ChangeDesc403Response.ts
models/ChangeDescRequest.ts
models/ChangeDisplayName200Response.ts models/ChangeDisplayName200Response.ts
models/ChangeDisplayName400Response.ts models/ChangeDisplayName400Response.ts
models/ChangeDisplayNameRequest.ts models/ChangeDisplayNameRequest.ts

View file

@ -15,6 +15,12 @@
import * as runtime from '../runtime'; import * as runtime from '../runtime';
import type { import type {
AllowGuestMessage200Response,
AllowGuestMessage403Response,
ChangeDesc200Response,
ChangeDesc400Response,
ChangeDesc403Response,
ChangeDescRequest,
ChangeDisplayName200Response, ChangeDisplayName200Response,
ChangeDisplayName400Response, ChangeDisplayName400Response,
ChangeDisplayNameRequest, ChangeDisplayNameRequest,
@ -57,6 +63,18 @@ import type {
StatusOtp500Response, StatusOtp500Response,
} from '../models/index'; } from '../models/index';
import { import {
AllowGuestMessage200ResponseFromJSON,
AllowGuestMessage200ResponseToJSON,
AllowGuestMessage403ResponseFromJSON,
AllowGuestMessage403ResponseToJSON,
ChangeDesc200ResponseFromJSON,
ChangeDesc200ResponseToJSON,
ChangeDesc400ResponseFromJSON,
ChangeDesc400ResponseToJSON,
ChangeDesc403ResponseFromJSON,
ChangeDesc403ResponseToJSON,
ChangeDescRequestFromJSON,
ChangeDescRequestToJSON,
ChangeDisplayName200ResponseFromJSON, ChangeDisplayName200ResponseFromJSON,
ChangeDisplayName200ResponseToJSON, ChangeDisplayName200ResponseToJSON,
ChangeDisplayName400ResponseFromJSON, ChangeDisplayName400ResponseFromJSON,
@ -139,6 +157,10 @@ import {
StatusOtp500ResponseToJSON, StatusOtp500ResponseToJSON,
} from '../models/index'; } from '../models/index';
export interface ChangeDescOperationRequest {
changeDescRequest: ChangeDescRequest;
}
export interface ChangeDisplayNameOperationRequest { export interface ChangeDisplayNameOperationRequest {
changeDisplayNameRequest: ChangeDisplayNameRequest; changeDisplayNameRequest: ChangeDisplayNameRequest;
} }
@ -172,6 +194,112 @@ export interface SigninRequest {
*/ */
export class OpenapiOtherApi extends runtime.BaseAPI { export class OpenapiOtherApi extends runtime.BaseAPI {
/**
*/
async allowGuestMessageRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<AllowGuestMessage200Response | StatusOtp401Response | AllowGuestMessage403Response>> {
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
let urlPath = `/api/user/allowGuestMessage`;
const response = await this.request({
path: urlPath,
method: 'POST',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
// CHANGED: Handle all status codes defined in the OpenAPI spec, not just 2xx responses
// This allows typed access to error responses (4xx, 5xx) and other status codes.
// The code routes responses based on the actual HTTP status code and returns
// appropriately typed ApiResponse wrappers for each status code.
if (response.status === 200) {
// Object response for status 200
return new runtime.JSONApiResponse(response, (jsonValue) => AllowGuestMessage200ResponseFromJSON(jsonValue));
}
if (response.status === 401) {
// Object response for status 401
return new runtime.JSONApiResponse(response, (jsonValue) => StatusOtp401ResponseFromJSON(jsonValue));
}
if (response.status === 403) {
// Object response for status 403
return new runtime.JSONApiResponse(response, (jsonValue) => AllowGuestMessage403ResponseFromJSON(jsonValue));
}
// CHANGED: Throw error if status code is not handled by any of the defined responses
// This ensures all code paths return a value and provides clear error messages for unexpected status codes
// Only throw if responses were defined but none matched the actual status code
throw new runtime.ResponseError(response, `Unexpected status code: ${response.status}. Expected one of: 200, 401, 403`);
}
/**
*/
async allowGuestMessage(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<AllowGuestMessage200Response | StatusOtp401Response | AllowGuestMessage403Response> {
const response = await this.allowGuestMessageRaw(initOverrides);
return await response.value();
}
/**
*/
async changeDescRaw(requestParameters: ChangeDescOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<ChangeDesc200Response | ChangeDesc400Response | ChangePassword401Response | ChangeDesc403Response>> {
if (requestParameters['changeDescRequest'] == null) {
throw new runtime.RequiredError(
'changeDescRequest',
'Required parameter "changeDescRequest" was null or undefined when calling changeDesc().'
);
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
let urlPath = `/api/user/changeDesc`;
const response = await this.request({
path: urlPath,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: ChangeDescRequestToJSON(requestParameters['changeDescRequest']),
}, initOverrides);
// CHANGED: Handle all status codes defined in the OpenAPI spec, not just 2xx responses
// This allows typed access to error responses (4xx, 5xx) and other status codes.
// The code routes responses based on the actual HTTP status code and returns
// appropriately typed ApiResponse wrappers for each status code.
if (response.status === 200) {
// Object response for status 200
return new runtime.JSONApiResponse(response, (jsonValue) => ChangeDesc200ResponseFromJSON(jsonValue));
}
if (response.status === 400) {
// Object response for status 400
return new runtime.JSONApiResponse(response, (jsonValue) => ChangeDesc400ResponseFromJSON(jsonValue));
}
if (response.status === 401) {
// Object response for status 401
return new runtime.JSONApiResponse(response, (jsonValue) => ChangePassword401ResponseFromJSON(jsonValue));
}
if (response.status === 403) {
// Object response for status 403
return new runtime.JSONApiResponse(response, (jsonValue) => ChangeDesc403ResponseFromJSON(jsonValue));
}
// CHANGED: Throw error if status code is not handled by any of the defined responses
// This ensures all code paths return a value and provides clear error messages for unexpected status codes
// Only throw if responses were defined but none matched the actual status code
throw new runtime.ResponseError(response, `Unexpected status code: ${response.status}. Expected one of: 200, 400, 401, 403`);
}
/**
*/
async changeDesc(requestParameters: ChangeDescOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<ChangeDesc200Response | ChangeDesc400Response | ChangePassword401Response | ChangeDesc403Response> {
const response = await this.changeDescRaw(requestParameters, initOverrides);
return await response.value();
}
/** /**
*/ */
async changeDisplayNameRaw(requestParameters: ChangeDisplayNameOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<ChangeDisplayName200Response | ChangeDisplayName400Response | ChangePassword401Response>> { async changeDisplayNameRaw(requestParameters: ChangeDisplayNameOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<ChangeDisplayName200Response | ChangeDisplayName400Response | ChangePassword401Response>> {
@ -288,6 +416,52 @@ export class OpenapiOtherApi extends runtime.BaseAPI {
return await response.value(); return await response.value();
} }
/**
*/
async denyGuestMessageRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<AllowGuestMessage200Response | StatusOtp401Response | AllowGuestMessage403Response>> {
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
let urlPath = `/api/user/denyGuestMessage`;
const response = await this.request({
path: urlPath,
method: 'POST',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
// CHANGED: Handle all status codes defined in the OpenAPI spec, not just 2xx responses
// This allows typed access to error responses (4xx, 5xx) and other status codes.
// The code routes responses based on the actual HTTP status code and returns
// appropriately typed ApiResponse wrappers for each status code.
if (response.status === 200) {
// Object response for status 200
return new runtime.JSONApiResponse(response, (jsonValue) => AllowGuestMessage200ResponseFromJSON(jsonValue));
}
if (response.status === 401) {
// Object response for status 401
return new runtime.JSONApiResponse(response, (jsonValue) => StatusOtp401ResponseFromJSON(jsonValue));
}
if (response.status === 403) {
// Object response for status 403
return new runtime.JSONApiResponse(response, (jsonValue) => AllowGuestMessage403ResponseFromJSON(jsonValue));
}
// CHANGED: Throw error if status code is not handled by any of the defined responses
// This ensures all code paths return a value and provides clear error messages for unexpected status codes
// Only throw if responses were defined but none matched the actual status code
throw new runtime.ResponseError(response, `Unexpected status code: ${response.status}. Expected one of: 200, 401, 403`);
}
/**
*/
async denyGuestMessage(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<AllowGuestMessage200Response | StatusOtp401Response | AllowGuestMessage403Response> {
const response = await this.denyGuestMessageRaw(initOverrides);
return await response.value();
}
/** /**
*/ */
async disableOtpRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<DisableOtp200Response | DisableOtp400Response | ChangePassword401Response | DisableOtp500Response>> { async disableOtpRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<DisableOtp200Response | DisableOtp400Response | ChangePassword401Response | DisableOtp500Response>> {

View file

@ -0,0 +1,93 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface AllowGuestMessage200Response
*/
export interface AllowGuestMessage200Response {
/**
*
* @type {string}
* @memberof AllowGuestMessage200Response
*/
kind: AllowGuestMessage200ResponseKindEnum;
/**
*
* @type {string}
* @memberof AllowGuestMessage200Response
*/
msg: AllowGuestMessage200ResponseMsgEnum;
}
/**
* @export
*/
export const AllowGuestMessage200ResponseKindEnum = {
Success: 'success'
} as const;
export type AllowGuestMessage200ResponseKindEnum = typeof AllowGuestMessage200ResponseKindEnum[keyof typeof AllowGuestMessage200ResponseKindEnum];
/**
* @export
*/
export const AllowGuestMessage200ResponseMsgEnum = {
GuestMessageSuccess: 'guestMessage.success'
} as const;
export type AllowGuestMessage200ResponseMsgEnum = typeof AllowGuestMessage200ResponseMsgEnum[keyof typeof AllowGuestMessage200ResponseMsgEnum];
/**
* Check if a given object implements the AllowGuestMessage200Response interface.
*/
export function instanceOfAllowGuestMessage200Response(value: object): value is AllowGuestMessage200Response {
if (!('kind' in value) || value['kind'] === undefined) return false;
if (!('msg' in value) || value['msg'] === undefined) return false;
return true;
}
export function AllowGuestMessage200ResponseFromJSON(json: any): AllowGuestMessage200Response {
return AllowGuestMessage200ResponseFromJSONTyped(json, false);
}
export function AllowGuestMessage200ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): AllowGuestMessage200Response {
if (json == null) {
return json;
}
return {
'kind': json['kind'],
'msg': json['msg'],
};
}
export function AllowGuestMessage200ResponseToJSON(json: any): AllowGuestMessage200Response {
return AllowGuestMessage200ResponseToJSONTyped(json, false);
}
export function AllowGuestMessage200ResponseToJSONTyped(value?: AllowGuestMessage200Response | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'kind': value['kind'],
'msg': value['msg'],
};
}

View file

@ -0,0 +1,93 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface AllowGuestMessage403Response
*/
export interface AllowGuestMessage403Response {
/**
*
* @type {string}
* @memberof AllowGuestMessage403Response
*/
kind: AllowGuestMessage403ResponseKindEnum;
/**
*
* @type {string}
* @memberof AllowGuestMessage403Response
*/
msg: AllowGuestMessage403ResponseMsgEnum;
}
/**
* @export
*/
export const AllowGuestMessage403ResponseKindEnum = {
Failure: 'failure'
} as const;
export type AllowGuestMessage403ResponseKindEnum = typeof AllowGuestMessage403ResponseKindEnum[keyof typeof AllowGuestMessage403ResponseKindEnum];
/**
* @export
*/
export const AllowGuestMessage403ResponseMsgEnum = {
GuestMessageFailureNotLoggedIn: 'guestMessage.failure.notLoggedIn'
} as const;
export type AllowGuestMessage403ResponseMsgEnum = typeof AllowGuestMessage403ResponseMsgEnum[keyof typeof AllowGuestMessage403ResponseMsgEnum];
/**
* Check if a given object implements the AllowGuestMessage403Response interface.
*/
export function instanceOfAllowGuestMessage403Response(value: object): value is AllowGuestMessage403Response {
if (!('kind' in value) || value['kind'] === undefined) return false;
if (!('msg' in value) || value['msg'] === undefined) return false;
return true;
}
export function AllowGuestMessage403ResponseFromJSON(json: any): AllowGuestMessage403Response {
return AllowGuestMessage403ResponseFromJSONTyped(json, false);
}
export function AllowGuestMessage403ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): AllowGuestMessage403Response {
if (json == null) {
return json;
}
return {
'kind': json['kind'],
'msg': json['msg'],
};
}
export function AllowGuestMessage403ResponseToJSON(json: any): AllowGuestMessage403Response {
return AllowGuestMessage403ResponseToJSONTyped(json, false);
}
export function AllowGuestMessage403ResponseToJSONTyped(value?: AllowGuestMessage403Response | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'kind': value['kind'],
'msg': value['msg'],
};
}

View file

@ -0,0 +1,93 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface ChangeDesc200Response
*/
export interface ChangeDesc200Response {
/**
*
* @type {string}
* @memberof ChangeDesc200Response
*/
kind: ChangeDesc200ResponseKindEnum;
/**
*
* @type {string}
* @memberof ChangeDesc200Response
*/
msg: ChangeDesc200ResponseMsgEnum;
}
/**
* @export
*/
export const ChangeDesc200ResponseKindEnum = {
Success: 'success'
} as const;
export type ChangeDesc200ResponseKindEnum = typeof ChangeDesc200ResponseKindEnum[keyof typeof ChangeDesc200ResponseKindEnum];
/**
* @export
*/
export const ChangeDesc200ResponseMsgEnum = {
ChangedescSuccess: 'changedesc.success'
} as const;
export type ChangeDesc200ResponseMsgEnum = typeof ChangeDesc200ResponseMsgEnum[keyof typeof ChangeDesc200ResponseMsgEnum];
/**
* Check if a given object implements the ChangeDesc200Response interface.
*/
export function instanceOfChangeDesc200Response(value: object): value is ChangeDesc200Response {
if (!('kind' in value) || value['kind'] === undefined) return false;
if (!('msg' in value) || value['msg'] === undefined) return false;
return true;
}
export function ChangeDesc200ResponseFromJSON(json: any): ChangeDesc200Response {
return ChangeDesc200ResponseFromJSONTyped(json, false);
}
export function ChangeDesc200ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChangeDesc200Response {
if (json == null) {
return json;
}
return {
'kind': json['kind'],
'msg': json['msg'],
};
}
export function ChangeDesc200ResponseToJSON(json: any): ChangeDesc200Response {
return ChangeDesc200ResponseToJSONTyped(json, false);
}
export function ChangeDesc200ResponseToJSONTyped(value?: ChangeDesc200Response | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'kind': value['kind'],
'msg': value['msg'],
};
}

View file

@ -0,0 +1,93 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface ChangeDesc400Response
*/
export interface ChangeDesc400Response {
/**
*
* @type {string}
* @memberof ChangeDesc400Response
*/
kind: ChangeDesc400ResponseKindEnum;
/**
*
* @type {string}
* @memberof ChangeDesc400Response
*/
msg: ChangeDesc400ResponseMsgEnum;
}
/**
* @export
*/
export const ChangeDesc400ResponseKindEnum = {
Failure: 'failure'
} as const;
export type ChangeDesc400ResponseKindEnum = typeof ChangeDesc400ResponseKindEnum[keyof typeof ChangeDesc400ResponseKindEnum];
/**
* @export
*/
export const ChangeDesc400ResponseMsgEnum = {
ChangedescFailureDescTooLong: 'changedesc.failure.descTooLong'
} as const;
export type ChangeDesc400ResponseMsgEnum = typeof ChangeDesc400ResponseMsgEnum[keyof typeof ChangeDesc400ResponseMsgEnum];
/**
* Check if a given object implements the ChangeDesc400Response interface.
*/
export function instanceOfChangeDesc400Response(value: object): value is ChangeDesc400Response {
if (!('kind' in value) || value['kind'] === undefined) return false;
if (!('msg' in value) || value['msg'] === undefined) return false;
return true;
}
export function ChangeDesc400ResponseFromJSON(json: any): ChangeDesc400Response {
return ChangeDesc400ResponseFromJSONTyped(json, false);
}
export function ChangeDesc400ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChangeDesc400Response {
if (json == null) {
return json;
}
return {
'kind': json['kind'],
'msg': json['msg'],
};
}
export function ChangeDesc400ResponseToJSON(json: any): ChangeDesc400Response {
return ChangeDesc400ResponseToJSONTyped(json, false);
}
export function ChangeDesc400ResponseToJSONTyped(value?: ChangeDesc400Response | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'kind': value['kind'],
'msg': value['msg'],
};
}

View file

@ -0,0 +1,93 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface ChangeDesc403Response
*/
export interface ChangeDesc403Response {
/**
*
* @type {string}
* @memberof ChangeDesc403Response
*/
kind: ChangeDesc403ResponseKindEnum;
/**
*
* @type {string}
* @memberof ChangeDesc403Response
*/
msg: ChangeDesc403ResponseMsgEnum;
}
/**
* @export
*/
export const ChangeDesc403ResponseKindEnum = {
Failure: 'failure'
} as const;
export type ChangeDesc403ResponseKindEnum = typeof ChangeDesc403ResponseKindEnum[keyof typeof ChangeDesc403ResponseKindEnum];
/**
* @export
*/
export const ChangeDesc403ResponseMsgEnum = {
ChangedescFailureNotLoggedIn: 'changedesc.failure.notLoggedIn'
} as const;
export type ChangeDesc403ResponseMsgEnum = typeof ChangeDesc403ResponseMsgEnum[keyof typeof ChangeDesc403ResponseMsgEnum];
/**
* Check if a given object implements the ChangeDesc403Response interface.
*/
export function instanceOfChangeDesc403Response(value: object): value is ChangeDesc403Response {
if (!('kind' in value) || value['kind'] === undefined) return false;
if (!('msg' in value) || value['msg'] === undefined) return false;
return true;
}
export function ChangeDesc403ResponseFromJSON(json: any): ChangeDesc403Response {
return ChangeDesc403ResponseFromJSONTyped(json, false);
}
export function ChangeDesc403ResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChangeDesc403Response {
if (json == null) {
return json;
}
return {
'kind': json['kind'],
'msg': json['msg'],
};
}
export function ChangeDesc403ResponseToJSON(json: any): ChangeDesc403Response {
return ChangeDesc403ResponseToJSONTyped(json, false);
}
export function ChangeDesc403ResponseToJSONTyped(value?: ChangeDesc403Response | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'kind': value['kind'],
'msg': value['msg'],
};
}

View file

@ -0,0 +1,66 @@
/* tslint:disable */
/* eslint-disable */
/**
* @fastify/swagger
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 9.6.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface ChangeDescRequest
*/
export interface ChangeDescRequest {
/**
*
* @type {string}
* @memberof ChangeDescRequest
*/
desc: string;
}
/**
* Check if a given object implements the ChangeDescRequest interface.
*/
export function instanceOfChangeDescRequest(value: object): value is ChangeDescRequest {
if (!('desc' in value) || value['desc'] === undefined) return false;
return true;
}
export function ChangeDescRequestFromJSON(json: any): ChangeDescRequest {
return ChangeDescRequestFromJSONTyped(json, false);
}
export function ChangeDescRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChangeDescRequest {
if (json == null) {
return json;
}
return {
'desc': json['desc'],
};
}
export function ChangeDescRequestToJSON(json: any): ChangeDescRequest {
return ChangeDescRequestToJSONTyped(json, false);
}
export function ChangeDescRequestToJSONTyped(value?: ChangeDescRequest | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'desc': value['desc'],
};
}

View file

@ -1,5 +1,11 @@
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
export * from './AllowGuestMessage200Response';
export * from './AllowGuestMessage403Response';
export * from './ChangeDesc200Response';
export * from './ChangeDesc400Response';
export * from './ChangeDesc403Response';
export * from './ChangeDescRequest';
export * from './ChangeDisplayName200Response'; export * from './ChangeDisplayName200Response';
export * from './ChangeDisplayName400Response'; export * from './ChangeDisplayName400Response';
export * from './ChangeDisplayNameRequest'; export * from './ChangeDisplayNameRequest';

View file

@ -20,7 +20,7 @@
"fastify-plugin": "^5.1.0", "fastify-plugin": "^5.1.0",
"joi": "^18.0.2", "joi": "^18.0.2",
"otp": "^1.1.2", "otp": "^1.1.2",
"typebox": "^1.0.63", "typebox": "^1.0.64",
"uuidv7": "^1.1.0" "uuidv7": "^1.1.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -5,7 +5,9 @@ CREATE TABLE IF NOT EXISTS user (
password TEXT, password TEXT,
otp TEXT, otp TEXT,
guest INTEGER NOT NULL DEFAULT 0, guest INTEGER NOT NULL DEFAULT 0,
oauth2 TEXT DEFAULT NULL oauth2 TEXT DEFAULT NULL,
desc TEXT NOT NULL DEFAULT "What a good day to be reviewing this project :D",
allow_guest_message INTEGER NOT NULL DEFAULT 1
); );

View file

@ -19,12 +19,19 @@ export interface IUserDb extends Database {
ensureUserOtpSecret(id: UserId): string | undefined, ensureUserOtpSecret(id: UserId): string | undefined,
deleteUserOtpSecret(id: UserId): void, deleteUserOtpSecret(id: UserId): void,
getAllUserFromProvider(provider: string): User[] | undefined, getAllUserFromProvider(provider: string): User[] | undefined,
getAllUsers(this: IUserDb): User[] | undefined, getAllUsers(this: IUserDb): User[] | undefined,
updateDisplayName(id: UserId, new_name: string): boolean, updateDisplayName(id: UserId, new_name: string): boolean,
getUserFromDisplayName(name: string): User | undefined, getUserFromDisplayName(name: string): User | undefined,
setUserDescription(id: UserId, newDescription: string): void,
getUserDescription(id: UserId): string | undefined,
allowGuestMessage(id: UserId): void,
denyGuestMessage(id: UserId): void,
getGuestMessage(id: UserId): boolean | undefined,
}; };
export const UserImpl: Omit<IUserDb, keyof Database> = { export const UserImpl: Omit<IUserDb, keyof Database> = {
@ -44,11 +51,11 @@ export const UserImpl: Omit<IUserDb, keyof Database> = {
}, },
getAllUsers(this: IUserDb): User[] { getAllUsers(this: IUserDb): User[] {
const rows = this.prepare('SELECT * FROM user').all() as Partial<User>[]; const rows = this.prepare('SELECT * FROM user').all() as Partial<User>[];
return rows return rows
.map(row => userFromRow(row)) .map(row => userFromRow(row))
.filter((u): u is User => u !== undefined); .filter((u): u is User => u !== undefined);
}, },
@ -182,6 +189,28 @@ export const UserImpl: Omit<IUserDb, keyof Database> = {
const res = this.prepare('SELECT * FROM user WHERE name = @name LIMIT 1').get({ name }) as User | undefined; const res = this.prepare('SELECT * FROM user WHERE name = @name LIMIT 1').get({ name }) as User | undefined;
return userFromRow(res); return userFromRow(res);
}, },
setUserDescription(this: IUserDb, id: UserId, desc: string): void {
this.prepare('UPDATE OR IGNORE user SET desc = @desc WHERE id = @id').run({ id, desc });
},
getUserDescription(this: IUserDb, id: UserId): string | undefined {
return this.prepare('SELECT desc FROM user WHERE id = @id').get({ id }) as string | undefined;
},
allowGuestMessage(this: IUserDb, id: UserId): void {
this.prepare('UPDATE OR IGNORE user SET allow_guest_message = @allow_guest_message WHERE id = @id').run({ id, allow_guest_message: 1 });
},
denyGuestMessage(this: IUserDb, id: UserId): void {
this.prepare('UPDATE OR IGNORE user SET allow_guest_message = @allow_guest_message WHERE id = @id').run({ id, allow_guest_message: 0 });
},
getGuestMessage(this: IUserDb, id: UserId): boolean | undefined {
return this.prepare('SELECT allow_guest_message FROM user WHERE id = @id').get({ id }) as boolean | undefined;
},
}; };
export type UserId = UUID; export type UserId = UUID;
@ -196,6 +225,9 @@ export type User = {
// will be split/merged from the `oauth2` column // will be split/merged from the `oauth2` column
readonly provider_name?: string; readonly provider_name?: string;
readonly provider_unique?: string; readonly provider_unique?: string;
readonly allow_guest_message: boolean,
readonly desc: string,
}; };
export async function verifyUserPassword( export async function verifyUserPassword(
@ -235,6 +267,8 @@ export function userFromRow(row?: Partial<Omit<User, 'provider_name' | 'provider
if (isNullish(row.id)) return undefined; if (isNullish(row.id)) return undefined;
if (isNullish(row.name)) return undefined; if (isNullish(row.name)) return undefined;
if (isNullish(row.guest)) return undefined; if (isNullish(row.guest)) return undefined;
if (isNullish(row.desc)) return undefined;
if (isNullish(row.allow_guest_message)) return undefined;
let provider_name = undefined; let provider_name = undefined;
let provider_unique = undefined; let provider_unique = undefined;
@ -254,5 +288,7 @@ export function userFromRow(row?: Partial<Omit<User, 'provider_name' | 'provider
otp: row.otp ?? undefined, otp: row.otp ?? undefined,
guest: !!(row.guest ?? true), guest: !!(row.guest ?? true),
provider_name, provider_unique, provider_name, provider_unique,
allow_guest_message: !!(row.allow_guest_message ?? true),
desc: row.desc ?? 'NO DESC ????',
}; };
} }

View file

@ -142,3 +142,10 @@ export function typeResponse<K extends string, T extends TProperties>(
export function isNullish<T>(v: T | undefined | null): v is null | undefined { export function isNullish<T>(v: T | undefined | null): v is null | undefined {
return v === null || v === undefined; return v === null || v === undefined;
} }
export function escape(s: string): string {
return s.replace(
/[^0-9A-Za-z ]/g,
c => '&#' + c.charCodeAt(0) + ';',
);
}

View file

@ -27,8 +27,7 @@
"fastify": "^5.6.2", "fastify": "^5.6.2",
"fastify-cli": "^7.4.1", "fastify-cli": "^7.4.1",
"fastify-plugin": "^5.1.0", "fastify-plugin": "^5.1.0",
"socket.io-client": "^4.8.1", "typebox": "^1.0.64"
"typebox": "^1.0.63"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.19.3", "@types/node": "^22.19.3",

View file

@ -27,7 +27,7 @@
"fastify": "^5.6.2", "fastify": "^5.6.2",
"fastify-plugin": "^5.1.0", "fastify-plugin": "^5.1.0",
"socket.io": "^4.8.1", "socket.io": "^4.8.1",
"typebox": "^1.0.63" "typebox": "^1.0.64"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.19.3", "@types/node": "^22.19.3",

View file

@ -3,6 +3,7 @@ import type { ClientProfil } from './chat_types';
import type { User } from '@shared/database/mixin/user'; import type { User } from '@shared/database/mixin/user';
import { getUserByName } from './getUserByName'; import { getUserByName } from './getUserByName';
import { Socket } from 'socket.io'; import { Socket } from 'socket.io';
import { escape } from '@shared/utils';
/** /**
* function makeProfil - translates the Users[] to a one user looking by name * function makeProfil - translates the Users[] to a one user looking by name
@ -13,7 +14,7 @@ import { Socket } from 'socket.io';
* @returns * @returns
*/ */
export async function makeProfil(fastify: FastifyInstance, user: string, socket: Socket): Promise <ClientProfil> { export async function makeProfil(fastify: FastifyInstance, user: string, socket: Socket): Promise<ClientProfil> {
let clientProfil!: ClientProfil; let clientProfil!: ClientProfil;
const users: User[] = fastify.db.getAllUsers() ?? []; const users: User[] = fastify.db.getAllUsers() ?? [];
@ -29,7 +30,7 @@ export async function makeProfil(fastify: FastifyInstance, user: string, socket:
user: `${allUsers.name}`, user: `${allUsers.name}`,
loginName: `${allUsers?.login ?? 'Guest'}`, loginName: `${allUsers?.login ?? 'Guest'}`,
userID: `${allUsers?.id ?? ''}`, userID: `${allUsers?.id ?? ''}`,
text: '', text: escape(allUsers.desc),
timestamp: Date.now(), timestamp: Date.now(),
SenderWindowID: socket.id, SenderWindowID: socket.id,
SenderName: '', SenderName: '',
@ -38,4 +39,4 @@ export async function makeProfil(fastify: FastifyInstance, user: string, socket:
}; };
} }
return clientProfil; return clientProfil;
}; };

View file

@ -1234,6 +1234,375 @@
] ]
} }
}, },
"/api/user/allowGuestMessage": {
"post": {
"operationId": "allowGuestMessage",
"responses": {
"200": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"success"
]
},
"msg": {
"enum": [
"guestMessage.success"
]
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"anyOf": [
{
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
},
{
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
}
]
}
}
}
},
"403": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"guestMessage.failure.notLoggedIn"
]
}
}
}
}
}
}
},
"tags": [
"openapi_other"
]
}
},
"/api/user/denyGuestMessage": {
"post": {
"operationId": "denyGuestMessage",
"responses": {
"200": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"success"
]
},
"msg": {
"enum": [
"guestMessage.success"
]
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"anyOf": [
{
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
},
{
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
}
]
}
}
}
},
"403": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"guestMessage.failure.notLoggedIn"
]
}
}
}
}
}
}
},
"tags": [
"openapi_other"
]
}
},
"/api/user/changeDesc": {
"post": {
"operationId": "changeDesc",
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"desc"
],
"properties": {
"desc": {
"type": "string"
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"success"
]
},
"msg": {
"enum": [
"changedesc.success"
]
}
}
}
}
}
},
"400": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"changedesc.failure.descTooLong"
]
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
}
}
}
},
"403": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"changedesc.failure.notLoggedIn"
]
}
}
}
}
}
}
},
"tags": [
"openapi_other"
]
}
},
"/api/user/changeDisplayName": { "/api/user/changeDisplayName": {
"put": { "put": {
"operationId": "changeDisplayName", "operationId": "changeDisplayName",

View file

@ -23,7 +23,6 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.39.2", "@eslint/js": "^9.39.2",
"@openapitools/openapi-generator-cli": "^2.25.2",
"@typescript-eslint/eslint-plugin": "^8.50.0", "@typescript-eslint/eslint-plugin": "^8.50.0",
"@typescript-eslint/parser": "^8.50.0", "@typescript-eslint/parser": "^8.50.0",
"eslint": "^9.39.2", "eslint": "^9.39.2",
@ -34,7 +33,7 @@
"vite": "^7.3.0" "vite": "^7.3.0"
}, },
"dependencies": { "dependencies": {
"@redocly/cli": "^2.12.7", "@redocly/cli": "^2.13.0",
"bindings": "^1.5.0" "bindings": "^1.5.0"
} }
} }

1467
src/pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -8,6 +8,366 @@
"schemas": {} "schemas": {}
}, },
"paths": { "paths": {
"/api/user/allowGuestMessage": {
"post": {
"operationId": "allowGuestMessage",
"responses": {
"200": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"success"
]
},
"msg": {
"enum": [
"guestMessage.success"
]
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"anyOf": [
{
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
},
{
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
}
]
}
}
}
},
"403": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"guestMessage.failure.notLoggedIn"
]
}
}
}
}
}
}
}
}
},
"/api/user/denyGuestMessage": {
"post": {
"operationId": "denyGuestMessage",
"responses": {
"200": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"success"
]
},
"msg": {
"enum": [
"guestMessage.success"
]
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"anyOf": [
{
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
},
{
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
}
]
}
}
}
},
"403": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"guestMessage.failure.notLoggedIn"
]
}
}
}
}
}
}
}
}
},
"/api/user/changeDesc": {
"post": {
"operationId": "changeDesc",
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"desc"
],
"properties": {
"desc": {
"type": "string"
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"success"
]
},
"msg": {
"enum": [
"changedesc.success"
]
}
}
}
}
}
},
"400": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"changedesc.failure.descTooLong"
]
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"notLoggedIn"
]
},
"msg": {
"enum": [
"auth.noCookie",
"auth.invalidKind",
"auth.noUser",
"auth.invalid"
]
}
}
}
}
}
},
"403": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"changedesc.failure.notLoggedIn"
]
}
}
}
}
}
}
}
}
},
"/api/user/changeDisplayName": { "/api/user/changeDisplayName": {
"put": { "put": {
"operationId": "changeDisplayName", "operationId": "changeDisplayName",

View file

@ -26,7 +26,7 @@
"fastify": "^5.6.2", "fastify": "^5.6.2",
"fastify-cli": "^7.4.1", "fastify-cli": "^7.4.1",
"fastify-plugin": "^5.1.0", "fastify-plugin": "^5.1.0",
"typebox": "^1.0.63" "typebox": "^1.0.64"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.19.3", "@types/node": "^22.19.3",

View file

@ -0,0 +1,47 @@
import { FastifyPluginAsync } from 'fastify';
import { isNullish, MakeStaticResponse, typeResponse } from '@shared/utils';
export const GuestMessageRes = {
'200': typeResponse('success', 'guestMessage.success'),
'403': typeResponse('failure', 'guestMessage.failure.notLoggedIn'),
};
export type GuestMessageRes = MakeStaticResponse<typeof GuestMessageRes>;
const allowRoute: FastifyPluginAsync = async (fastify, _opts): Promise<void> => {
void _opts;
fastify.post(
'/api/user/allowGuestMessage',
{ schema: { response: GuestMessageRes, operationId: 'allowGuestMessage' }, config: { requireAuth: true } },
async function(req, res) {
if (isNullish(req.authUser)) { return res.makeResponse(403, 'failure', 'guestMessage.failure.notLoggedIn'); }
this.db.allowGuestMessage(req.authUser.id);
return res.makeResponse(200, 'success', 'guestMessage.success');
},
);
};
const denyRoute: FastifyPluginAsync = async (fastify, _opts): Promise<void> => {
void _opts;
fastify.post(
'/api/user/denyGuestMessage',
{ schema: { response: GuestMessageRes, operationId: 'denyGuestMessage' }, config: { requireAuth: true } },
async function(req, res) {
if (isNullish(req.authUser)) { return res.makeResponse(403, 'failure', 'guestMessage.failure.notLoggedIn'); }
this.db.denyGuestMessage(req.authUser.id);
return res.makeResponse(200, 'success', 'guestMessage.success');
},
);
};
const route: FastifyPluginAsync = async (fastify): Promise<void> => {
fastify.register(allowRoute);
fastify.register(denyRoute);
};
export default route;

View file

@ -0,0 +1,36 @@
import { FastifyPluginAsync } from 'fastify';
import { Static, Type } from 'typebox';
import { isNullish, MakeStaticResponse, typeResponse } from '@shared/utils';
export const ChangeDescRes = {
'200': typeResponse('success', 'changedesc.success'),
'400': typeResponse('failure', 'changedesc.failure.descTooLong'),
'403': typeResponse('failure', 'changedesc.failure.notLoggedIn'),
};
export type ChangeDescRes = MakeStaticResponse<typeof ChangeDescRes>;
export const ChangeDescBody = Type.Object({ desc: Type.String() });
export type ChangeDescBody = Static<typeof ChangeDescBody>;
const route: FastifyPluginAsync = async (fastify, _opts): Promise<void> => {
void _opts;
fastify.post<{ Body: ChangeDescBody }>(
'/api/user/changeDesc',
{ schema: { body: ChangeDescBody, response: ChangeDescRes, operationId: 'changeDesc' }, config: { requireAuth: true } },
async function(req, res) {
if (isNullish(req.authUser)) { return res.makeResponse(403, 'failure', 'changedesc.failure.notLoggedIn'); }
if (req.body.desc.length > 75) {
return res.makeResponse(400, 'failure', 'changedesc.failure.descTooLong');
}
this.db.setUserDescription(req.authUser.id, req.body.desc);
return res.makeResponse(200, 'success', 'changedesc.success');
},
);
};
export default route;