From 2255d0d15d9a0cc6088d5b19c819a49b1b013379 Mon Sep 17 00:00:00 2001 From: Isaac Date: Sun, 9 Feb 2025 23:12:53 +0000 Subject: [PATCH] feat: separate user and admin auth, redirect to settings after invite --- package.json | 9 +- pnpm-lock.yaml | 386 +++++++++++++++--------------------- src/http.js | 55 ++--- src/lib/http.js | 1 - src/routes/auth/callback.js | 46 ++++- src/routes/auth/login.js | 44 ++++ src/routes/auth/logout.js | 3 - src/routes/invite.js | 26 +-- 8 files changed, 265 insertions(+), 305 deletions(-) delete mode 100644 src/lib/http.js create mode 100644 src/routes/auth/login.js diff --git a/package.json b/package.json index 5186c20..5b2c9d4 100644 --- a/package.json +++ b/package.json @@ -52,9 +52,9 @@ "@eartharoid/dbf": "^0.4.2", "@eartharoid/dtf": "^2.0.1", "@eartharoid/i18n": "^1.2.1", - "@fastify/cookie": "^9.4.0", - "@fastify/jwt": "^8.0.1", - "@fastify/oauth2": "^7.9.0", + "@fastify/cookie": "^11.0.2", + "@fastify/jwt": "^9.0.3", + "@fastify/multipart": "^9.0.3", "@prisma/client": "^4.16.2", "archiver": "^7.0.1", "boxen": "^7.1.1", @@ -62,7 +62,7 @@ "cryptr": "^6.3.0", "discord.js": "^14.17.3", "dotenv": "^16.4.7", - "fastify": "^4.29.0", + "fastify": "^5.2.1", "figlet": "^1.8.0", "fs-extra": "^10.1.0", "keyv": "^4.5.4", @@ -80,6 +80,7 @@ "spacetime": "^7.7.0", "terminal-link": "^2.1.1", "threads": "^1.7.0", + "unzipper": "^0.12.3", "yaml": "^2.7.0" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index badf212..ffe3e08 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,14 +21,14 @@ importers: specifier: ^1.2.1 version: 1.2.1 '@fastify/cookie': - specifier: ^9.4.0 - version: 9.4.0 + specifier: ^11.0.2 + version: 11.0.2 '@fastify/jwt': - specifier: ^8.0.1 - version: 8.0.1 - '@fastify/oauth2': - specifier: ^7.9.0 - version: 7.9.0 + specifier: ^9.0.3 + version: 9.0.3 + '@fastify/multipart': + specifier: ^9.0.3 + version: 9.0.3 '@prisma/client': specifier: ^4.16.2 version: 4.16.2(prisma@4.16.2) @@ -51,8 +51,8 @@ importers: specifier: ^16.4.7 version: 16.4.7 fastify: - specifier: ^4.29.0 - version: 4.29.0 + specifier: ^5.2.1 + version: 5.2.1 figlet: specifier: ^1.8.0 version: 1.8.0 @@ -104,6 +104,9 @@ importers: threads: specifier: ^1.7.0 version: 1.7.0 + unzipper: + specifier: ^0.12.3 + version: 0.12.3 yaml: specifier: ^2.7.0 version: 2.7.0 @@ -300,44 +303,38 @@ packages: resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@fastify/ajv-compiler@3.6.0': - resolution: {integrity: sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==} + '@fastify/ajv-compiler@4.0.2': + resolution: {integrity: sha512-Rkiu/8wIjpsf46Rr+Fitd3HRP+VsxUFDDeag0hs9L0ksfnwx2g7SPQQTFL0E8Qv+rfXzQOxBJnjUB9ITUDjfWQ==} - '@fastify/cookie@9.4.0': - resolution: {integrity: sha512-Th+pt3kEkh4MQD/Q2q1bMuJIB5NX/D5SwSpOKu3G/tjoGbwfpurIMJsWSPS0SJJ4eyjtmQ8OipDQspf8RbUOlg==} + '@fastify/busboy@3.1.1': + resolution: {integrity: sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==} - '@fastify/error@3.4.1': - resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} + '@fastify/cookie@11.0.2': + resolution: {integrity: sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==} - '@fastify/fast-json-stringify-compiler@4.3.0': - resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==} + '@fastify/deepmerge@2.0.2': + resolution: {integrity: sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==} - '@fastify/jwt@8.0.1': - resolution: {integrity: sha512-295bd7V6bDCnZOu8MAQgM6r7V1KILB+kdEq1q6nbHfXCnML569n7NSo3WzeLDG6IAqDl+Rhzi1vjxwaNHhRCBA==} + '@fastify/error@4.0.0': + resolution: {integrity: sha512-OO/SA8As24JtT1usTUTKgGH7uLvhfwZPwlptRi2Dp5P4KKmJI3gvsZ8MIHnNwDs4sLf/aai5LzTyl66xr7qMxA==} - '@fastify/merge-json-schemas@0.1.1': - resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==} + '@fastify/fast-json-stringify-compiler@5.0.2': + resolution: {integrity: sha512-YdR7gqlLg1xZAQa+SX4sMNzQHY5pC54fu9oC5aYSUqBhyn6fkLkrdtKlpVdCNPlwuUuXA1PjFTEmvMF6ZVXVGw==} - '@fastify/oauth2@7.9.0': - resolution: {integrity: sha512-OsMr+M2FI7ib/UKZ8hC4SRnUBQqgJ0EsvAhn1qrdYJ9K/U5OwaM2sQM8fLEYbKYQRlH0oxC7lvdTm8Ncd5+ukA==} + '@fastify/forwarded@3.0.0': + resolution: {integrity: sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==} - '@hapi/boom@10.0.1': - resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==} + '@fastify/jwt@9.0.3': + resolution: {integrity: sha512-5OjeozLzwhMhrOkadHG9FhS5S3wNVIN6ADhBJd/x3VJIWptlRdc1ORksA6NHJ1ihvuAb0IOVK9giaCZTelnMSg==} - '@hapi/bourne@3.0.0': - resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} + '@fastify/merge-json-schemas@0.2.1': + resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==} - '@hapi/hoek@11.0.7': - resolution: {integrity: sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==} + '@fastify/multipart@9.0.3': + resolution: {integrity: sha512-pJogxQCrT12/6I5Fh6jr3narwcymA0pv4B0jbC7c6Bl9wnrxomEUnV0d26w6gUls7gSXmhG8JGRMmHFIPsxt1g==} - '@hapi/hoek@9.3.0': - resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} - - '@hapi/topo@5.1.0': - resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} - - '@hapi/wreck@18.1.0': - resolution: {integrity: sha512-0z6ZRCmFEfV/MQqkQomJ7sl/hyxvcZM7LtuVqN3vdAO4vM9eBbowl0kaqQj9EJJQab+3Uuh1GxbGIBFy4NfJ4w==} + '@fastify/proxy-addr@5.0.0': + resolution: {integrity: sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==} '@humanwhocodes/config-array@0.13.0': resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} @@ -417,15 +414,6 @@ packages: resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==} engines: {node: '>=v14.0.0', npm: '>=7.0.0'} - '@sideway/address@4.1.5': - resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} - - '@sideway/formula@3.0.1': - resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} - - '@sideway/pinpoint@2.0.0': - resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} - '@tsconfig/node10@1.0.11': resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} @@ -488,14 +476,6 @@ packages: add-stream@1.0.0: resolution: {integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==} - ajv-formats@2.1.1: - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - ajv-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: @@ -577,8 +557,8 @@ packages: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} - avvio@8.4.0: - resolution: {integrity: sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==} + avvio@9.1.0: + resolution: {integrity: sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==} b4a@1.6.7: resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} @@ -599,6 +579,9 @@ packages: bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + bn.js@4.12.1: resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==} @@ -808,13 +791,9 @@ packages: engines: {node: '>=14'} hasBin: true - cookie-signature@1.2.2: - resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} - engines: {node: '>=6.6.0'} - - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + engines: {node: '>=18'} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -900,6 +879,10 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -926,6 +909,9 @@ packages: resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} + duplexer2@0.1.4: + resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -1035,9 +1021,6 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} - fast-content-type-parse@1.1.0: - resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==} - fast-decode-uri-component@1.0.1: resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} @@ -1050,12 +1033,12 @@ packages: fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - fast-json-stringify@5.16.1: - resolution: {integrity: sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==} + fast-json-stringify@6.0.1: + resolution: {integrity: sha512-s7SJE83QKBZwg54dIbD5rCtzOBVD43V1ReWXXYqBgwCwHLYAAT0RQc/FmrQglXqWPpz6omtryJQOau5jI4Nrvg==} - fast-jwt@4.0.5: - resolution: {integrity: sha512-QnpNdn0955GT7SlT8iMgYfhTsityUWysrQjM+Q7bGFijLp6+TNWzlbSMPvgalbrQGRg4ZaHZgMcns5fYOm5avg==} - engines: {node: '>=16'} + fast-jwt@5.0.5: + resolution: {integrity: sha512-Ch94zewwBjRznO0r76NFI5FDT0lOtnzkWVO4r7+d7E2WKuf7WW1FVOWRpv7QGEFlXzz9OAayrb5BhEmkOkwjhg==} + engines: {node: '>=20'} fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} @@ -1067,9 +1050,6 @@ packages: resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} engines: {node: '>=6'} - fast-uri@2.4.0: - resolution: {integrity: sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==} - fast-uri@3.0.6: resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} @@ -1077,11 +1057,11 @@ packages: resolution: {integrity: sha512-KH6p+Z8AKPXnmA7+Iz2Lh8ARCMr+8WNPVludm1LGkZoD2MjY6LVnRMtTKhkdzI+jr0RzQWXKzKyBJm1zoHEL4Q==} engines: {node: '>=0.10.0'} - fastify-plugin@4.5.1: - resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==} + fastify-plugin@5.0.1: + resolution: {integrity: sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==} - fastify@4.29.0: - resolution: {integrity: sha512-MaaUHUGcCgC8fXQDsDtioaCcag1fmPJ9j64vAKunqZF4aSub040ZGi/ag8NGE2714yREPOKZuHCfpPzuUD3UQQ==} + fastify@5.2.1: + resolution: {integrity: sha512-rslrNBF67eg8/Gyn7P2URV8/6pz8kSAscFL4EThZJ8JBMaXacVdVE4hmUcnPNKERl5o/xTiBSLfdowBRhVF1WA==} fastparallel@2.4.1: resolution: {integrity: sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==} @@ -1112,8 +1092,8 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - find-my-way@8.2.2: - resolution: {integrity: sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA==} + find-my-way@9.1.0: + resolution: {integrity: sha512-Y5jIsuYR4BwWDYYQ2A/RWWE6gD8a0FMgtU+HOq1WKku+Cwdz8M1v8wcAmRXXM1/iqtoqg06v+LjAxMYbCjViMw==} engines: {node: '>=14'} find-up@2.1.0: @@ -1139,10 +1119,6 @@ packages: resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} - forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -1307,9 +1283,9 @@ packages: resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==} engines: {node: '>=8.0.0'} - ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} + ipaddr.js@2.2.0: + resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} + engines: {node: '>= 10'} is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -1391,9 +1367,6 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - joi@17.13.3: - resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} - js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1414,8 +1387,8 @@ packages: json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-schema-ref-resolver@1.0.1: - resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==} + json-schema-ref-resolver@2.0.1: + resolution: {integrity: sha512-HG0SIB9X4J8bwbxCbnd5FfPEbcXAJYTi1pBJeP/QPON+w8ovSME8iRG+ElHNxZNX2Qh6eYn1GdzJFS4cDFfx0Q==} json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -1458,8 +1431,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - light-my-request@5.14.0: - resolution: {integrity: sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA==} + light-my-request@6.5.1: + resolution: {integrity: sha512-0q82RyxIextuDtkA0UDofhPHIiQ2kmpa7fwElCSlm/8nQl36cDU1Cw+CAO90Es0lReH2HChClKL84I86Nc52hg==} lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} @@ -1667,6 +1640,9 @@ packages: resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} hasBin: true + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + nodemon@2.0.22: resolution: {integrity: sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==} engines: {node: '>=8.10.0'} @@ -1869,9 +1845,6 @@ packages: process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - process-warning@3.0.0: - resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} - process-warning@4.0.1: resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} @@ -1879,10 +1852,6 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} - proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - pstree.remy@1.1.8: resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} @@ -1993,8 +1962,8 @@ packages: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} - ret@0.4.3: - resolution: {integrity: sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==} + ret@0.5.0: + resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==} engines: {node: '>=10'} reusify@1.0.4: @@ -2026,8 +1995,8 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - safe-regex2@3.1.0: - resolution: {integrity: sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==} + safe-regex2@4.0.1: + resolution: {integrity: sha512-goqsB+bSlOmVX+CiFX2PFc1OV88j5jvBqIM+DgqrucHnUguAUNtiNOs+aTadq2NqsLQ+TQ3UEVG3gtSFcdlkCg==} safe-stable-stringify@2.5.0: resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} @@ -2036,8 +2005,8 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - secure-json-parse@2.7.0: - resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + secure-json-parse@3.0.2: + resolution: {integrity: sha512-H6nS2o8bWfpFEV6U38sOSjS7bTbdgbCGU9wEM6W14P5H0QOsz94KCusifV44GpHDTu2nqZbuDNhTzu+mjDSw1w==} semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} @@ -2086,9 +2055,6 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - simple-oauth2@5.1.0: - resolution: {integrity: sha512-gWDa38Ccm4MwlG5U7AlcJxPv3lvr80dU7ARJWrGdgvOKyzSj1gr3GBPN1rABTedAYvC/LsGYoFuFxwDBPtGEbw==} - simple-update-notifier@1.1.0: resolution: {integrity: sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==} engines: {node: '>=8.10.0'} @@ -2350,6 +2316,9 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} + unzipper@0.12.3: + resolution: {integrity: sha512-PZ8hTS+AqcGxsaQntl3IRBw65QrBI6lxzqDEL7IAo/XCEqRTKGfOX56Vea5TH9SZczRVxuzk1re04z/YjuYCJA==} + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -2705,62 +2674,53 @@ snapshots: '@eslint/js@8.57.1': {} - '@fastify/ajv-compiler@3.6.0': + '@fastify/ajv-compiler@4.0.2': dependencies: ajv: 8.17.1 - ajv-formats: 2.1.1(ajv@8.17.1) - fast-uri: 2.4.0 + ajv-formats: 3.0.1(ajv@8.17.1) + fast-uri: 3.0.6 - '@fastify/cookie@9.4.0': + '@fastify/busboy@3.1.1': {} + + '@fastify/cookie@11.0.2': dependencies: - cookie-signature: 1.2.2 - fastify-plugin: 4.5.1 + cookie: 1.0.2 + fastify-plugin: 5.0.1 - '@fastify/error@3.4.1': {} + '@fastify/deepmerge@2.0.2': {} - '@fastify/fast-json-stringify-compiler@4.3.0': + '@fastify/error@4.0.0': {} + + '@fastify/fast-json-stringify-compiler@5.0.2': dependencies: - fast-json-stringify: 5.16.1 + fast-json-stringify: 6.0.1 - '@fastify/jwt@8.0.1': + '@fastify/forwarded@3.0.0': {} + + '@fastify/jwt@9.0.3': dependencies: - '@fastify/error': 3.4.1 + '@fastify/error': 4.0.0 '@lukeed/ms': 2.0.2 - fast-jwt: 4.0.5 - fastify-plugin: 4.5.1 + fast-jwt: 5.0.5 + fastify-plugin: 5.0.1 steed: 1.1.3 - '@fastify/merge-json-schemas@0.1.1': + '@fastify/merge-json-schemas@0.2.1': dependencies: - fast-deep-equal: 3.1.3 + dequal: 2.0.3 - '@fastify/oauth2@7.9.0': + '@fastify/multipart@9.0.3': dependencies: - '@fastify/cookie': 9.4.0 - fastify-plugin: 4.5.1 - simple-oauth2: 5.1.0 - transitivePeerDependencies: - - supports-color + '@fastify/busboy': 3.1.1 + '@fastify/deepmerge': 2.0.2 + '@fastify/error': 4.0.0 + fastify-plugin: 5.0.1 + secure-json-parse: 3.0.2 - '@hapi/boom@10.0.1': + '@fastify/proxy-addr@5.0.0': dependencies: - '@hapi/hoek': 11.0.7 - - '@hapi/bourne@3.0.0': {} - - '@hapi/hoek@11.0.7': {} - - '@hapi/hoek@9.3.0': {} - - '@hapi/topo@5.1.0': - dependencies: - '@hapi/hoek': 9.3.0 - - '@hapi/wreck@18.1.0': - dependencies: - '@hapi/boom': 10.0.1 - '@hapi/bourne': 3.0.0 - '@hapi/hoek': 11.0.7 + '@fastify/forwarded': 3.0.0 + ipaddr.js: 2.2.0 '@humanwhocodes/config-array@0.13.0': dependencies: @@ -2830,14 +2790,6 @@ snapshots: '@sapphire/snowflake@3.5.3': {} - '@sideway/address@4.1.5': - dependencies: - '@hapi/hoek': 9.3.0 - - '@sideway/formula@3.0.1': {} - - '@sideway/pinpoint@2.0.0': {} - '@tsconfig/node10@1.0.11': {} '@tsconfig/node12@1.0.11': {} @@ -2887,10 +2839,6 @@ snapshots: add-stream@1.0.0: {} - ajv-formats@2.1.1(ajv@8.17.1): - optionalDependencies: - ajv: 8.17.1 - ajv-formats@3.0.1(ajv@8.17.1): optionalDependencies: ajv: 8.17.1 @@ -2992,9 +2940,9 @@ snapshots: atomic-sleep@1.0.0: {} - avvio@8.4.0: + avvio@9.1.0: dependencies: - '@fastify/error': 3.4.1 + '@fastify/error': 4.0.0 fastq: 1.18.0 b4a@1.6.7: {} @@ -3013,6 +2961,8 @@ snapshots: file-uri-to-path: 1.0.0 optional: true + bluebird@3.7.2: {} + bn.js@4.12.1: {} boxen@7.1.1: @@ -3276,9 +3226,7 @@ snapshots: meow: 8.1.2 split2: 3.2.2 - cookie-signature@1.2.2: {} - - cookie@0.7.2: {} + cookie@1.0.2: {} core-util-is@1.0.3: {} @@ -3342,6 +3290,8 @@ snapshots: deep-is@0.1.4: {} + dequal@2.0.3: {} + didyoumean@1.2.2: {} diff@4.0.2: {} @@ -3376,6 +3326,10 @@ snapshots: dotenv@16.4.7: {} + duplexer2@0.1.4: + dependencies: + readable-stream: 2.3.8 + eastasianwidth@0.2.0: {} ecdsa-sig-formatter@1.0.11: @@ -3518,8 +3472,6 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 - fast-content-type-parse@1.1.0: {} - fast-decode-uri-component@1.0.1: {} fast-deep-equal@3.1.3: {} @@ -3528,17 +3480,16 @@ snapshots: fast-json-stable-stringify@2.1.0: {} - fast-json-stringify@5.16.1: + fast-json-stringify@6.0.1: dependencies: - '@fastify/merge-json-schemas': 0.1.1 + '@fastify/merge-json-schemas': 0.2.1 ajv: 8.17.1 ajv-formats: 3.0.1(ajv@8.17.1) - fast-deep-equal: 3.1.3 - fast-uri: 2.4.0 - json-schema-ref-resolver: 1.0.1 + fast-uri: 3.0.6 + json-schema-ref-resolver: 2.0.1 rfdc: 1.4.1 - fast-jwt@4.0.5: + fast-jwt@5.0.5: dependencies: '@lukeed/ms': 2.0.2 asn1.js: 5.4.1 @@ -3553,32 +3504,29 @@ snapshots: fast-redact@3.5.0: {} - fast-uri@2.4.0: {} - fast-uri@3.0.6: {} fastfall@1.5.1: dependencies: reusify: 1.0.4 - fastify-plugin@4.5.1: {} + fastify-plugin@5.0.1: {} - fastify@4.29.0: + fastify@5.2.1: dependencies: - '@fastify/ajv-compiler': 3.6.0 - '@fastify/error': 3.4.1 - '@fastify/fast-json-stringify-compiler': 4.3.0 + '@fastify/ajv-compiler': 4.0.2 + '@fastify/error': 4.0.0 + '@fastify/fast-json-stringify-compiler': 5.0.2 + '@fastify/proxy-addr': 5.0.0 abstract-logging: 2.0.1 - avvio: 8.4.0 - fast-content-type-parse: 1.1.0 - fast-json-stringify: 5.16.1 - find-my-way: 8.2.2 - light-my-request: 5.14.0 + avvio: 9.1.0 + fast-json-stringify: 6.0.1 + find-my-way: 9.1.0 + light-my-request: 6.5.1 pino: 9.6.0 - process-warning: 3.0.0 - proxy-addr: 2.0.7 + process-warning: 4.0.1 rfdc: 1.4.1 - secure-json-parse: 2.7.0 + secure-json-parse: 3.0.2 semver: 7.7.0 toad-cache: 3.7.0 @@ -3613,11 +3561,11 @@ snapshots: dependencies: to-regex-range: 5.0.1 - find-my-way@8.2.2: + find-my-way@9.1.0: dependencies: fast-deep-equal: 3.1.3 fast-querystring: 1.1.2 - safe-regex2: 3.1.0 + safe-regex2: 4.0.1 find-up@2.1.0: dependencies: @@ -3646,8 +3594,6 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - forwarded@0.2.0: {} - fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 @@ -3815,7 +3761,7 @@ snapshots: strip-ansi: 6.0.1 through: 2.3.8 - ipaddr.js@1.9.1: {} + ipaddr.js@2.2.0: {} is-arrayish@0.2.1: {} @@ -3871,14 +3817,6 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 - joi@17.13.3: - dependencies: - '@hapi/hoek': 9.3.0 - '@hapi/topo': 5.1.0 - '@sideway/address': 4.1.5 - '@sideway/formula': 3.0.1 - '@sideway/pinpoint': 2.0.0 - js-tokens@4.0.0: {} js-yaml@4.1.0: @@ -3897,9 +3835,9 @@ snapshots: json-parse-even-better-errors@2.3.1: {} - json-schema-ref-resolver@1.0.1: + json-schema-ref-resolver@2.0.1: dependencies: - fast-deep-equal: 3.1.3 + dequal: 2.0.3 json-schema-traverse@0.4.1: {} @@ -3940,10 +3878,10 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - light-my-request@5.14.0: + light-my-request@6.5.1: dependencies: - cookie: 0.7.2 - process-warning: 3.0.0 + cookie: 1.0.2 + process-warning: 4.0.1 set-cookie-parser: 2.7.1 lilconfig@2.1.0: {} @@ -4137,6 +4075,8 @@ snapshots: node-gyp-build@4.8.4: optional: true + node-int64@0.4.0: {} + nodemon@2.0.22: dependencies: chokidar: 3.6.0 @@ -4335,17 +4275,10 @@ snapshots: process-nextick-args@2.0.1: {} - process-warning@3.0.0: {} - process-warning@4.0.1: {} process@0.11.10: {} - proxy-addr@2.0.7: - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - pstree.remy@1.1.8: {} punycode@2.3.1: {} @@ -4458,7 +4391,7 @@ snapshots: onetime: 7.0.0 signal-exit: 4.1.0 - ret@0.4.3: {} + ret@0.5.0: {} reusify@1.0.4: {} @@ -4482,15 +4415,15 @@ snapshots: safe-buffer@5.2.1: {} - safe-regex2@3.1.0: + safe-regex2@4.0.1: dependencies: - ret: 0.4.3 + ret: 0.5.0 safe-stable-stringify@2.5.0: {} safer-buffer@2.1.2: {} - secure-json-parse@2.7.0: {} + secure-json-parse@3.0.2: {} semver@5.7.2: {} @@ -4520,15 +4453,6 @@ snapshots: signal-exit@4.1.0: {} - simple-oauth2@5.1.0: - dependencies: - '@hapi/hoek': 11.0.7 - '@hapi/wreck': 18.1.0 - debug: 4.4.0 - joi: 17.13.3 - transitivePeerDependencies: - - supports-color - simple-update-notifier@1.1.0: dependencies: semver: 7.0.0 @@ -4778,6 +4702,14 @@ snapshots: universalify@2.0.1: {} + unzipper@0.12.3: + dependencies: + bluebird: 3.7.2 + duplexer2: 0.1.4 + fs-extra: 11.3.0 + graceful-fs: 4.2.11 + node-int64: 0.4.0 + uri-js@4.4.1: dependencies: punycode: 2.3.1 diff --git a/src/http.js b/src/http.js index 4283c8d..33f8e53 100644 --- a/src/http.js +++ b/src/http.js @@ -1,14 +1,16 @@ const fastify = require('fastify')({ trustProxy: process.env.HTTP_TRUST_PROXY === 'true' }); -const oauth = require('@fastify/oauth2'); -const { randomBytes } = require('crypto'); const { short } = require('leeks.js'); const { join } = require('path'); const { files } = require('node-dir'); const { getPrivilegeLevel } = require('./lib/users'); +const { format } = require('util'); process.env.ORIGIN = process.env.HTTP_INTERNAL || process.env.HTTP_EXTERNAL; module.exports = async client => { + // for file uploads + fastify.register(require('@fastify/multipart'), { limits: { fileSize: 2**27 } }); // 128 MiB + // cookies plugin, must be registered before oauth2 since oauth2@7.2.0 fastify.register(require('@fastify/cookie')); @@ -21,36 +23,6 @@ module.exports = async client => { secret: process.env.ENCRYPTION_KEY, }); - // oauth2 plugin - fastify.states = new Map(); - fastify.register(oauth, { - callbackUri: `${process.env.HTTP_EXTERNAL}/auth/callback`, - callbackUriParams: { prompt: 'none' }, - checkStateFunction: async req => { - if (req.query.state !== req.cookies['oauth2-redirect-state']) { - throw new Error('Invalid state'); - } - return true; - }, - credentials: { - auth: oauth.DISCORD_CONFIGURATION, - client: { - id: client.user.id, - secret: process.env.DISCORD_SECRET, - }, - }, - generateStateFunction: req => { - const state = randomBytes(8).toString('hex'); - fastify.states.set(state, req.query.r); - return state; - }, - name: 'discord', - redirectStateCookieName: 'oauth2-redirect-state', - scope: ['applications.commands.permissions.update', 'guilds', 'identify'], - startRedirectPath: '/auth/login', - }); - - // auth fastify.decorate('authenticate', async (req, res) => { try { @@ -111,7 +83,14 @@ module.exports = async client => { error: 'Unavailable For Legal Reasons', message: 'This guild has been banned for breaking the terms of service.', statusCode: 451, - + }); + } + if (!req.user.scopes?.includes('applications.commands.permissions.update')) { + return res.code(401).send({ + elevate: 'admin', + error: 'Unauthorised', + message: 'Extra scopes required; reauthenticate.', + statusCode: 401, }); } const guildMember = await guild.members.fetch(userId); @@ -161,11 +140,15 @@ module.exports = async client => { : '&a') + responseTime + 'ms'; const level = req.routeOptions.url === '/status' ? 'debug' - : req.routeOptions.url === '/*' + : req.routeOptions.url === '/*' ? 'verbose' : 'info'; - client.log[level].http(short(`${req.id} ${req.ip} ${req.method} ${req.routeOptions.url ?? '*'} &m-+>&r ${status}&b in ${responseTime}`)); - if (!req.routeOptions.url) client.log.verbose.http(`${req.id} ${req.method} ${req.url}`); + client.log[level].http( + format( + short(`${req.id} ${req.ip} ${req.method} %s &m-+>&r ${status}&b in ${responseTime}`), + req.url, + ), + ); done(); }); diff --git a/src/lib/http.js b/src/lib/http.js deleted file mode 100644 index 31ebf84..0000000 --- a/src/lib/http.js +++ /dev/null @@ -1 +0,0 @@ -module.exports.domain = new URL(process.env.HTTP_EXTERNAL).hostname; diff --git a/src/routes/auth/callback.js b/src/routes/auth/callback.js index e453544..acf49cd 100644 --- a/src/routes/auth/callback.js +++ b/src/routes/auth/callback.js @@ -1,7 +1,27 @@ -const { domain } = require('../../lib/http'); - module.exports.get = () => ({ - handler: async function (req, res) { // MUST NOT use arrow function syntax + handler: async function (req, res) { + const cookie = req.cookies['oauth2-state']; + if (!cookie) { + return res.code(400).send({ + error: 'Bad Request', + message: 'State is missing.', + statusCode: 400, + + }); + } + + const state = new URLSearchParams(cookie); + if (state.get('secret') !== req.query.state) { + return res.code(400).send({ + error: 'Bad Request', + message: 'Invalid state.', + statusCode: 400, + + }); + } + + // TODO: check if req.query.permissions are correct + const data = await (await fetch('https://discord.com/api/oauth2/token', { body: new URLSearchParams({ client_id: req.routeOptions.config.client.user.id, @@ -14,22 +34,30 @@ module.exports.get = () => ({ method: 'POST', })).json(); - const user = await (await fetch('https://discordapp.com/api/users/@me', { headers: { 'Authorization': `Bearer ${data.access_token}` } })).json(); + const redirect = (data.guild?.id && `/settings/${data.guild?.id}`) || state.get('redirect') || '/'; + + const bearerOptions = { headers: { 'Authorization': `Bearer ${data.access_token}` } }; + const user = await (await fetch('https://discordapp.com/api/users/@me', bearerOptions)).json(); + + let scopes; + if (data.scope) { + scopes = data.scope.split(' '); + } else { + const auth = await (await fetch('https://discordapp.com/api/oauth2/@me', bearerOptions)).json(); + scopes = auth.scopes; + } + const token = this.jwt.sign({ accessToken: data.access_token, avatar: user.avatar, expiresAt: Date.now() + (data.expires_in * 1000), id: user.id, locale: user.locale, + scopes, username: user.username, }); - // note: if data.guild is present, guild_id and permissions should also be in req.query - const redirect = this.states.get(req.query.state) || (data.guild?.id && `/settings/${data.guild?.id}`) || '/'; - this.states.delete(req.query.state); - res.setCookie('token', token, { - domain, httpOnly: true, maxAge: data.expires_in, path: '/', diff --git a/src/routes/auth/login.js b/src/routes/auth/login.js new file mode 100644 index 0000000..d405ad5 --- /dev/null +++ b/src/routes/auth/login.js @@ -0,0 +1,44 @@ +const { randomBytes } = require('crypto'); + +module.exports.get = () => ({ + handler: async function (req, res) { + const { client } = req.routeOptions.config; + + const state = new URLSearchParams({ + redirect: req.query.r ?? '', + secret: randomBytes(8).toString('hex'), + }); + + res.setCookie('oauth2-state', state.toString(), { + httpOnly: true, + sameSite: 'lax', + }); + + const params = { + client_id: client.user.id, + // ? prompt: 'none', + redirect_uri: `${process.env.HTTP_EXTERNAL}/auth/callback`, // if not set defaults to first allowed + response_type: 'code', + scope: 'guilds identify', + state: state.get('secret'), + }; + + if (req.query.invite !== undefined) { + params.prompt = 'consent'; // already implied by the bot scope + params.scope = 'applications.commands applications.commands.permissions.update bot ' + params.scope; + params.integration_type = '0'; + params.permissions = '268561488'; + if (req.query.guild) { + params.guild_id = req.query.guild; + params.disable_guild_select = 'true'; + } + } else if (req.query.role === 'admin') { // invite implies admin already + params.scope = 'applications.commands.permissions.update ' + params.scope; + } + + const url = new URL('https://discord.com/oauth2/authorize'); + url.search = new URLSearchParams(params); + + res.redirect(url.toString()); + }, +}); diff --git a/src/routes/auth/logout.js b/src/routes/auth/logout.js index 65a19c6..ad1428f 100644 --- a/src/routes/auth/logout.js +++ b/src/routes/auth/logout.js @@ -1,5 +1,3 @@ -const { domain } = require('../../lib/http'); - module.exports.get = fastify => ({ handler: async function (req, res) { const { accessToken } = req.user; @@ -15,7 +13,6 @@ module.exports.get = fastify => ({ }); res.clearCookie('token', { - domain, httpOnly: true, path: '/', sameSite: 'Strict', diff --git a/src/routes/invite.js b/src/routes/invite.js index 286af8f..ec75102 100644 --- a/src/routes/invite.js +++ b/src/routes/invite.js @@ -1,29 +1,5 @@ -const { randomBytes } = require('crypto'); - module.exports.get = () => ({ handler: async function (req, res) { - const { client } = req.routeOptions.config; - - const state = randomBytes(8).toString('hex'); - this.states.set(state, null); - - const url = new URL('https://discord.com/oauth2/authorize'); - url.searchParams.set('response_type', 'code'); - url.searchParams.set('client_id', client.user.id); - url.searchParams.set('prompt', 'none'); - url.searchParams.set('redirect_uri', `${process.env.HTTP_EXTERNAL}/auth/callback`); // window.location.origin - url.searchParams.set('scope', 'applications.commands applications.commands.permissions.update bot guilds identify'); - url.searchParams.set('permissions', '268561488'); - - if (req.query.guild) { - url.searchParams.set('guild_id', req.query.guild); - url.searchParams.set('disable_guild_select', 'true'); - } - - res.setCookie('oauth2-redirect-state', state, { - httpOnly: true, - sameSite: 'lax', - }); - res.redirect(url.toString()); + res.redirect(`/auth/login?invite&guild=${req.query.guild || ''}`); }, });