mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
Better mock oauth server (#416)
This commit is contained in:
parent
8bd73f0d99
commit
84ba75895e
@ -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": {
|
||||
|
||||
@ -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 `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Sign-in</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<style>
|
||||
body {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="min-h-screen flex items-center justify-center p-4">
|
||||
<div class="card w-full max-w-md p-8">
|
||||
<h1 class="text-2xl font-bold mb-6 text-center">Mock OAuth Sign-in</h1>
|
||||
<form method="post" action="/interaction/${uid}/login" class="space-y-4">
|
||||
<div>
|
||||
<label for="login" class="block text-gray-700">Email</label>
|
||||
<input id="login" type="email" name="login" required
|
||||
class="mt-1 block w-full border border-gray-300 rounded px-3 py-2 focus:outline-none focus:ring focus:border-blue-300" />
|
||||
</div>
|
||||
<button type="submit"
|
||||
class="w-full bg-black hover:bg-gray-800 text-white font-semibold py-2 px-4 rounded">
|
||||
Sign in
|
||||
</button>
|
||||
</form>
|
||||
<!-- Container for displaying stored account emails -->
|
||||
<div id="stored-accounts" class="mt-4"></div>
|
||||
<details class="mt-6 bg-gray-50 rounded p-2">
|
||||
<summary class="cursor-pointer text-sm text-gray-600">Debug</summary>
|
||||
<pre class="mt-1 text-xs text-gray-500 overflow-x-auto">${JSON.stringify(debugInfo, null, 2)}</pre>
|
||||
</details>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const storedAccountsContainer = document.getElementById('stored-accounts');
|
||||
const emailInput = document.getElementById('login');
|
||||
if (!storedAccountsContainer || !emailInput) return;
|
||||
|
||||
// Retrieve stored accounts from localStorage or initialize as an empty array
|
||||
let storedAccounts = JSON.parse(localStorage.getItem('previousAccounts') || '[]');
|
||||
|
||||
// Get the form element to submit later
|
||||
const form = document.querySelector('form');
|
||||
if (!form) return;
|
||||
|
||||
// Render the list of stored accounts and add direct submission on click.
|
||||
const renderStoredAccounts = () => {
|
||||
if (storedAccounts.length > 0) {
|
||||
let listHtml = '<h2 class="text-lg font-medium text-gray-700 mb-2">Previously Used Accounts</h2>';
|
||||
listHtml += '<div class="grid gap-2">';
|
||||
storedAccounts.forEach((account) => {
|
||||
listHtml += \`
|
||||
<div class="p-3 bg-white border border-gray-200 rounded-lg shadow-sm hover:bg-gray-50 transition-shadow cursor-pointer" data-email="\${account}">
|
||||
<div class="flex items-center">
|
||||
<div class="h-8 w-8 rounded-full bg-gray-100 flex items-center justify-center mr-3">
|
||||
<span class="text-gray-600 font-medium">\${account.charAt(0).toUpperCase()}</span>
|
||||
</div>
|
||||
<span class="text-gray-700">\${account}</span>
|
||||
</div>
|
||||
</div>
|
||||
\`;
|
||||
});
|
||||
listHtml += '</div>';
|
||||
storedAccountsContainer.innerHTML = listHtml;
|
||||
|
||||
// Add click event listeners that set the email and submit the form directly.
|
||||
storedAccountsContainer.querySelectorAll('[data-email]').forEach(card => {
|
||||
card.addEventListener('click', () => {
|
||||
const selectedEmail = card.getAttribute('data-email') || '';
|
||||
emailInput.value = selectedEmail;
|
||||
form.submit();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
storedAccountsContainer.innerHTML = '';
|
||||
}
|
||||
};
|
||||
|
||||
renderStoredAccounts();
|
||||
|
||||
// On form submission, store the email if it's not already stored.
|
||||
form.addEventListener('submit', () => {
|
||||
const email = emailInput.value.trim();
|
||||
if (email && !storedAccounts.includes(email)) {
|
||||
storedAccounts.push(email);
|
||||
localStorage.setItem('previousAccounts', JSON.stringify(storedAccounts));
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
};
|
||||
|
||||
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}`);
|
||||
});
|
||||
|
||||
234
pnpm-lock.yaml
234
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: {}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user