diff --git a/apps/oauth-mock-server/package.json b/apps/oauth-mock-server/package.json index d79da5224..6d2b0fabe 100644 --- a/apps/oauth-mock-server/package.json +++ b/apps/oauth-mock-server/package.json @@ -10,8 +10,11 @@ "lint": "eslint ." }, "dependencies": { - "@types/oidc-provider": "^8.5.1", "@stackframe/stack-shared": "workspace:*", + "@types/express": "^5.0.0", + "@types/oidc-provider": "^8.5.1", + "body-parser": "^1.20.3", + "express": "^4.21.2", "oidc-provider": "^8.5.1" }, "devDependencies": { diff --git a/apps/oauth-mock-server/src/index.ts b/apps/oauth-mock-server/src/index.ts index 00f31b5de..4ec8d98ec 100644 --- a/apps/oauth-mock-server/src/index.ts +++ b/apps/oauth-mock-server/src/index.ts @@ -1,41 +1,235 @@ -import Provider, { Configuration } from 'oidc-provider'; +import { strict as assert } from 'assert'; +import express from 'express'; +import Provider, { errors } from 'oidc-provider'; -// terminate this Node.js process if parent terminates -process.on('disconnect', function() { - console.log('parent exited; exiting too'); - process.exit(); -}); +const { SessionNotFound } = errors; -const port = Number.parseInt(process.env.PORT || "8114"); - -const mockedProviders = [ - "github", - "facebook", - "google", - "microsoft", - "spotify", - "discord", - "gitlab", - "bitbucket", - "x", +const port = process.env.PORT || 8114; +const providerIds = [ + 'github', + 'facebook', + 'google', + 'microsoft', + 'spotify', + 'discord', + 'gitlab', + 'bitbucket', + 'x', ]; +const clients = providerIds.map((id) => ({ + client_id: id, + client_secret: 'MOCK-SERVER-SECRET', + redirect_uris: [`http://localhost:8102/api/v1/auth/oauth/callback/${id}`], +})); -const configuration: Configuration = { - clients: mockedProviders.map((providerId) => ({ - client_id: providerId, - client_secret: 'MOCK-SERVER-SECRET', - redirect_uris: [ - `http://localhost:8102/api/v1/auth/oauth/callback/${providerId}`, - ], - })), - ttl: { - // we make sessions short so it asks us for our login again after a minute, instead of automatically logging us in with the already-logged-in session - Session: 60, - }, +const configuration = { + clients, + ttl: { Session: 60 }, + findAccount: async (ctx: any, sub: string) => ({ + accountId: sub, + async claims() { + return { sub, email: sub }; + }, + }), }; const oidc = new Provider(`http://localhost:${port}`, configuration); +const app = express(); -oidc.listen(port, () => { - console.log(`oidc-provider listening on port ${port}, check http://localhost:${port}/.well-known/openid-configuration`); +app.use(express.urlencoded({ extended: false })); + +const renderLoginView = ({ uid, debugInfo }: { uid: string, debugInfo: unknown }): string => { + return ` + + + + + + Sign-in + + + + +
+

Mock OAuth Sign-in

+
+
+ + +
+ +
+ +
+
+ Debug +
${JSON.stringify(debugInfo, null, 2)}
+
+ +
+ + + `; +}; + +const setNoCache = (req: express.Request, res: express.Response, next: express.NextFunction) => { + res.set('cache-control', 'no-store'); + next(); +}; + +app.get('/interaction/:uid', setNoCache, async (req: express.Request, res: express.Response, next: express.NextFunction) => { + try { + const { uid, prompt, params, session, grantId } = await oidc.interactionDetails(req, res); + const debugInfo = { params, prompt, session }; + + if (prompt.name === 'login') { + res.send(renderLoginView({ + uid, + debugInfo, + })); + } else if (prompt.name === 'consent') { + // Automatically approve consent without showing an approval page. + if (!session) throw new Error('No session found'); + const accountId = session.accountId; + const { details } = prompt; + + let grant = grantId + ? await oidc.Grant.find(grantId) + : new oidc.Grant({ accountId, clientId: params.client_id as string }); + if (!grant) { + throw new Error('Failed to create or find grant'); + } + if (Array.isArray(details.missingOIDCScope)) { + grant.addOIDCScope(details.missingOIDCScope.join(' ')); + } + if (Array.isArray(details.missingOIDCClaims)) { + grant.addOIDCClaims(details.missingOIDCClaims); + } + if (details.missingResourceScopes && typeof details.missingResourceScopes === 'object') { + for (const [indicator, scopes] of Object.entries(details.missingResourceScopes)) { + if (Array.isArray(scopes)) { + grant.addResourceScope(indicator, scopes.join(' ')); + } + } + } + const newGrantId = await grant.save(); + const consent: { grantId?: string } = {}; + if (!grantId) consent.grantId = newGrantId; + const result = { consent }; + await oidc.interactionFinished(req, res, result, { mergeWithLastSubmission: true }); + } else { + res.send('Unknown prompt'); + } + } catch (err) { + next(err); + } +}); + +app.post('/interaction/:uid/login', setNoCache, async (req, res, next) => { + try { + const { prompt } = await oidc.interactionDetails(req, res); + assert.strictEqual(prompt.name, 'login', 'Expected login prompt'); + const result = { login: { accountId: req.body.login, remember: false } }; + await oidc.interactionFinished(req, res, result, { mergeWithLastSubmission: false }); + } catch (err) { + next(err); + } +}); + +// The POST consent route has been removed as consent is now auto-approved. + +app.get('/interaction/:uid/abort', setNoCache, async (req, res, next) => { + try { + const result = { + error: 'access_denied', + error_description: 'End-User aborted interaction', + }; + await oidc.interactionFinished(req, res, result, { mergeWithLastSubmission: false }); + } catch (err) { + next(err); + } +}); + +app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => { + if (err instanceof SessionNotFound) { + res.status(410).send('Session not found or expired'); + } else { + next(err); + } +}); + +app.use(oidc.callback()); + +app.listen(port, () => { + console.log(`Server is running on http://localhost:${port}`); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f6ec1bc68..fa24aaa26 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -419,9 +419,18 @@ importers: '@stackframe/stack-shared': specifier: workspace:* version: link:../../packages/stack-shared + '@types/express': + specifier: ^5.0.0 + version: 5.0.0 '@types/oidc-provider': specifier: ^8.5.1 version: 8.5.1 + body-parser: + specifier: ^1.20.3 + version: 1.20.3 + express: + specifier: ^4.21.2 + version: 4.21.2 oidc-provider: specifier: ^8.5.1 version: 8.5.1 @@ -5330,11 +5339,11 @@ packages: '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - '@types/express-serve-static-core@4.19.5': - resolution: {integrity: sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==} + '@types/express-serve-static-core@5.0.6': + resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==} - '@types/express@4.17.21': - resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + '@types/express@5.0.0': + resolution: {integrity: sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==} '@types/geojson@7946.0.15': resolution: {integrity: sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA==} @@ -5833,6 +5842,9 @@ packages: resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} engines: {node: '>= 0.4'} + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + array-includes@3.1.8: resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} engines: {node: '>= 0.4'} @@ -6013,6 +6025,10 @@ packages: bn.js@4.12.0: resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -6442,6 +6458,9 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + cookie@0.4.2: resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} engines: {node: '>= 0.6'} @@ -6450,6 +6469,10 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} + cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} + engines: {node: '>= 0.6'} + cookies@0.9.1: resolution: {integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==} engines: {node: '>= 0.8'} @@ -6848,6 +6871,10 @@ packages: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + encoding-sniffer@0.2.0: resolution: {integrity: sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==} @@ -7209,6 +7236,10 @@ packages: resolution: {integrity: sha512-tCsc7WXTjrTx4ZjYLplcqrI3o4mYJ+Z6YspeuGL8tbt/hHoMchwBwtKfwM09svEY86iRapY93vUqQttcNuIO5Q==} engines: {node: '>=6.0.0'} + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} @@ -7232,6 +7263,10 @@ packages: resolution: {integrity: sha512-6CX17Cu+rC2Fi2CyZ4CkgVG3hLl6BFsdAxfXiZkmDFIDY4mRx2y2spdeH6dqPHI9rP+AsHEfGeKz84Uuw7+Pmg==} engines: {node: ^v12.20.0 || >=v14.13.0} + express@4.21.2: + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} + engines: {node: '>= 0.10.0'} + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -7291,6 +7326,10 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} + engines: {node: '>= 0.8'} + find-root@1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} @@ -7354,6 +7393,10 @@ packages: resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} engines: {node: '>= 6'} + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} @@ -7833,6 +7876,10 @@ packages: resolution: {integrity: sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.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'} @@ -8440,6 +8487,9 @@ packages: resolution: {integrity: sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==} engines: {node: '>=10'} + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -8583,6 +8633,11 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -8942,9 +8997,6 @@ packages: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} - object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - object-inspect@1.13.2: resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} engines: {node: '>= 0.4'} @@ -9144,6 +9196,9 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + path-to-regexp@3.3.0: resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==} @@ -9398,6 +9453,10 @@ packages: resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} engines: {node: '>=12.0.0'} + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -9426,6 +9485,10 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} @@ -9460,6 +9523,10 @@ packages: resolution: {integrity: sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==} engines: {node: '>= 0.6'} + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + raw-body@2.5.2: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} @@ -9904,12 +9971,20 @@ packages: engines: {node: '>=10'} hasBin: true + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} serve-handler@6.1.6: resolution: {integrity: sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==} + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} + serve@14.2.4: resolution: {integrity: sha512-qy1S34PJ/fcY8gjVGszDB3EXiPSk5FKhUa7tQe0UPRddxRidc2V6cNHPNewbE1D7MAkgLuWEt3Vw56vYy73tzQ==} engines: {node: '>= 14'} @@ -10812,6 +10887,10 @@ packages: util@0.10.4: resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true @@ -12290,7 +12369,7 @@ snapshots: '@eslint/eslintrc@1.4.1': dependencies: ajv: 6.12.6 - debug: 4.3.5 + debug: 4.3.7 espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -12382,7 +12461,7 @@ snapshots: '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.5 + debug: 4.3.7 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -15434,7 +15513,7 @@ snapshots: '@types/cookies@0.9.0': dependencies: '@types/connect': 3.4.38 - '@types/express': 4.17.21 + '@types/express': 5.0.0 '@types/keygrip': 1.0.6 '@types/node': 20.17.6 @@ -15492,17 +15571,17 @@ snapshots: '@types/estree@1.0.6': {} - '@types/express-serve-static-core@4.19.5': + '@types/express-serve-static-core@5.0.6': dependencies: '@types/node': 20.17.6 '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 - '@types/express@4.17.21': + '@types/express@5.0.0': dependencies: '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.5 + '@types/express-serve-static-core': 5.0.6 '@types/qs': 6.9.15 '@types/serve-static': 1.15.7 @@ -16049,6 +16128,8 @@ snapshots: call-bind: 1.0.7 is-array-buffer: 3.0.4 + array-flatten@1.1.1: {} + array-includes@3.1.8: dependencies: call-bind: 1.0.7 @@ -16288,6 +16369,23 @@ snapshots: bn.js@4.12.0: {} + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + boolbase@1.0.0: {} boxen@7.0.0: @@ -16747,10 +16845,14 @@ snapshots: convert-source-map@2.0.0: {} + cookie-signature@1.0.6: {} + cookie@0.4.2: {} cookie@0.6.0: {} + cookie@0.7.1: {} + cookies@0.9.1: dependencies: depd: 2.0.0 @@ -17118,6 +17220,8 @@ snapshots: encodeurl@1.0.2: {} + encodeurl@2.0.0: {} + encoding-sniffer@0.2.0: dependencies: iconv-lite: 0.6.3 @@ -17830,6 +17934,8 @@ snapshots: eta@3.4.0: {} + etag@1.8.1: {} + eventemitter3@4.0.7: {} events@3.3.0: {} @@ -17862,6 +17968,42 @@ snapshots: export-to-csv@1.4.0: {} + express@4.21.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.1 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + extend@3.0.2: {} extendable-error@0.1.7: {} @@ -17912,6 +18054,18 @@ snapshots: dependencies: to-regex-range: 5.0.1 + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + find-root@1.1.0: {} find-up@3.0.0: @@ -17968,6 +18122,8 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 + forwarded@0.2.0: {} + fraction.js@4.3.7: {} frame-ticker@1.0.3: @@ -18625,6 +18781,8 @@ snapshots: ip-regex@5.0.0: {} + ipaddr.js@1.9.1: {} + ipaddr.js@2.2.0: {} is-alphabetical@2.0.1: {} @@ -19336,6 +19494,8 @@ snapshots: type-fest: 0.13.1 yargs-parser: 18.1.3 + merge-descriptors@1.0.3: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -19638,6 +19798,8 @@ snapshots: dependencies: mime-db: 1.52.0 + mime@1.6.0: {} + mimic-fn@2.1.0: {} mimic-fn@4.0.0: {} @@ -20050,8 +20212,6 @@ snapshots: object-hash@3.0.0: {} - object-inspect@1.13.1: {} - object-inspect@1.13.2: {} object-keys@1.1.1: {} @@ -20283,6 +20443,8 @@ snapshots: lru-cache: 10.2.2 minipass: 7.1.2 + path-to-regexp@0.1.12: {} + path-to-regexp@3.3.0: {} path-to-regexp@6.2.2: {} @@ -20557,6 +20719,11 @@ snapshots: '@types/node': 20.17.6 long: 5.2.3 + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + proxy-from-env@1.1.0: {} pseudomap@1.0.2: {} @@ -20582,6 +20749,10 @@ snapshots: pngjs: 5.0.0 yargs: 15.4.1 + qs@6.13.0: + dependencies: + side-channel: 1.0.6 + querystringify@2.2.0: {} queue-microtask@1.2.3: {} @@ -20608,6 +20779,8 @@ snapshots: range-parser@1.2.0: {} + range-parser@1.2.1: {} + raw-body@2.5.2: dependencies: bytes: 3.1.2 @@ -21210,6 +21383,24 @@ snapshots: semver@7.6.3: {} + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 @@ -21224,6 +21415,15 @@ snapshots: path-to-regexp: 3.3.0 range-parser: 1.2.0 + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + serve@14.2.4: dependencies: '@zeit/schemas': 2.36.0 @@ -21354,7 +21554,7 @@ snapshots: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 - object-inspect: 1.13.1 + object-inspect: 1.13.2 siginfo@2.0.0: {} @@ -22418,6 +22618,8 @@ snapshots: dependencies: inherits: 2.0.3 + utils-merge@1.0.1: {} + uuid@9.0.1: {} uzip@0.20201231.0: {}