diff --git a/package-lock.json b/package-lock.json index 110544433f..13fbe4bf28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4776,6 +4776,11 @@ "node": ">= 8" } }, + "node_modules/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, "node_modules/crypto-random-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", @@ -16337,6 +16342,7 @@ "@types/node-fetch": "^2.6.2", "api": "^6.1.0", "content-type": "^1.0.5", + "crypto-js": "^4.1.1", "find-cache-dir": "^3.3.2", "flat-cache": "^3.0.4", "flatted": "^3.2.7", @@ -20081,6 +20087,11 @@ "which": "^2.0.1" } }, + "crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, "crypto-random-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", @@ -26178,10 +26189,11 @@ "@types/node": "^20.2.5", "@types/node-fetch": "^2.6.2", "@types/ssri": "^7.1.1", - "api": "*", + "api": "^6.1.0", "caseless": "^0.12.0", "chai": "^4.3.7", "content-type": "^1.0.5", + "crypto-js": "*", "eslint": "^8.34.0", "express": "^4.18.2", "find-cache-dir": "^3.3.2", diff --git a/packages/node/package.json b/packages/node/package.json index 4c480ac084..aeb6cc6ada 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -29,6 +29,7 @@ "@types/node-fetch": "^2.6.2", "api": "^6.1.0", "content-type": "^1.0.5", + "crypto-js": "^4.1.1", "find-cache-dir": "^3.3.2", "flat-cache": "^3.0.4", "flatted": "^3.2.7", diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 1624ad27a4..c765590d4d 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -6,7 +6,6 @@ import flatted from 'flatted'; import { getProjectBaseUrl } from './lib/get-project-base-url'; import { log } from './lib/log'; import { buildSetupView } from './lib/setup-readme-view'; -import { testMetrics } from './lib/test-metrics'; import { testVerifyWebhook } from './lib/test-verify-webhook'; import verifyWebhook from './lib/verify-webhook'; @@ -68,6 +67,7 @@ const findApiKey = (req, keys: [ApiKey]) => { // See comment at the auth definition below let apiKey = ''; +let readmeProject; const readme = userFunction => { // IDK if this is the best thing to do, but feels @@ -79,12 +79,11 @@ const readme = userFunction => { } return async (req, res, next) => { readmeSDK.auth(apiKey); - let readmeProject; try { readmeProject = (await readmeSDK.getProject()).data; } catch (e) { // TODO: better way of handling this error - console.log('Error fetching project, is your ReadMe API key correct'); + console.log('Error fetching project, is your ReadMe API key correct?'); console.log(e); } const baseUrl = `${req.protocol}://${req.get('host')}${req.baseUrl}`; @@ -102,16 +101,12 @@ const readme = userFunction => { const { grouping } = splitIntoUserAndConfig(user); return res.send(grouping); } else if (req.path === '/readme-setup' && env === 'development') { - const setupHtml = buildSetupView({ baseUrl }); + const setupHtml = buildSetupView({ baseUrl, subdomain: readmeProject.subdomain, apiKey }); return res.send(setupHtml); } else if (req.path === '/webhook-test' && env === 'development') { const email = req.query.email; const webhookData = await testVerifyWebhook(baseUrl, email, readmeProject.jwtSecret); return res.json({ ...webhookData }); - } else if (req.path === '/metrics-test' && env === 'development') { - // TODO: not implemented yet - const metricsData = await testMetrics(apiKey); - return res.json({ ...metricsData }); } const user = await userFunction(req, res); @@ -134,6 +129,8 @@ const readme = userFunction => { // readme.auth('api-key'); function auth(key) { apiKey = key; + // Reset the cache for the ReadMe project if the api key changes + readmeProject = undefined; return readme; } diff --git a/packages/node/src/lib/setup-readme-view.ts b/packages/node/src/lib/setup-readme-view.ts index 3a7f42bd6f..8adab0ed85 100644 --- a/packages/node/src/lib/setup-readme-view.ts +++ b/packages/node/src/lib/setup-readme-view.ts @@ -1,4 +1,6 @@ -export function buildSetupView({ baseUrl }) { +import sha512 from 'crypto-js/sha512'; + +export function buildSetupView({ baseUrl, apiKey, subdomain }) { const webhookVerifiedHtml = `
@@ -124,18 +126,16 @@ export function buildSetupView({ baseUrl }) { `; const metricsScriptHtml = ` - fetch('${baseUrl}/metrics-test') - .then(response => response.json()) - .then(data => { - const { metricsVerified } = data; - document.getElementById('metrics-test').classList.add('hidden'); - if (!metricsVerified) { - document.getElementById('metrics-fail').classList.remove('hidden'); - } else { - document.getElementById('metrics-success').classList.remove('hidden'); - window.metricsSuccess = true; - } - }); + const token = '${sha512(apiKey).toString()}'; + const query = new URLSearchParams(\`token=\${token}&subdomain=${subdomain}\`); + const socket = new WebSocket(new URL(\`?\${query}\`, 'wss://m.readme.io')); + socket.addEventListener('message', async ({ data }) => { + document.getElementById('metrics-test').classList.add('hidden'); + document.getElementById('metrics-success').classList.remove('hidden'); + }); + + // TODO: should we do something here if it takes too long? + // Maybe show some trouble shooting steps? `; return ` diff --git a/packages/node/src/lib/test-metrics.ts b/packages/node/src/lib/test-metrics.ts deleted file mode 100644 index 59695185f0..0000000000 --- a/packages/node/src/lib/test-metrics.ts +++ /dev/null @@ -1,7 +0,0 @@ -// This function should check our metrics backend to see if a request was successful -// if yes, return the details of the call -export async function testMetrics(apiKey) { - return { - metricsVerified: true, - }; -}