From 2e0482da2953d24fbab25a8f62d2995decc7ed94 Mon Sep 17 00:00:00 2001 From: Wan <495709+wa0x6e@users.noreply.github.com> Date: Tue, 24 Oct 2023 13:20:54 +0700 Subject: [PATCH] fix: `/api/spaces/ID` should pull data from DB instead of cache (#725) * fix: /api/spaces/ID should pull data from DB * Update src/helpers/spaces.ts --------- Co-authored-by: Chaitanya --- package.json | 2 +- src/api.ts | 17 +++++--- src/helpers/spaces.ts | 18 +++++++++ test/e2e/space.test.ts | 55 +++++++++++++++++++++++++- test/fixtures/spaces.ts | 13 ++++++ yarn.lock | 87 ++--------------------------------------- 6 files changed, 100 insertions(+), 92 deletions(-) create mode 100644 test/fixtures/spaces.ts diff --git a/package.json b/package.json index 30aa5459..9bc1ca58 100644 --- a/package.json +++ b/package.json @@ -55,10 +55,10 @@ "eslint": "^8.28.0", "jest": "^29.6.1", "jest-environment-node-single-context": "^29.1.0", + "node-fetch": "^2.7", "nodemon": "^2.0.19", "prettier": "^3.0.3", "start-server-and-test": "^2.0.0", - "supertest": "^6.3.3", "ts-jest": "^29.1.1" }, "engines": { diff --git a/src/api.ts b/src/api.ts index da6b2d1c..aeb30df6 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,5 +1,6 @@ import express from 'express'; -import { spaces } from './helpers/spaces'; +import { capture } from '@snapshot-labs/snapshot-sentry'; +import { getSpace } from './helpers/spaces'; import { name, version } from '../package.json'; import { sendError } from './helpers/utils'; @@ -25,14 +26,18 @@ router.get('/', (req, res) => { }); }); -router.get('/spaces/:key', (req, res) => { +router.get('/spaces/:key', async (req, res) => { const { key } = req.params; - if (!spaces[key]) { - return sendError(res, 'space not found', 404); + try { + return res.json(await getSpace(key)); + } catch (e: any) { + if (e.message !== 'NOT_FOUND') { + capture(e); + return sendError(res, 'server_error', 500); + } + return sendError(res, 'not_found', 404); } - - return res.json(spaces[key]); }); router.get('/spaces/:key/poke', async (req, res) => { diff --git a/src/helpers/spaces.ts b/src/helpers/spaces.ts index b917e132..40fd3c2e 100644 --- a/src/helpers/spaces.ts +++ b/src/helpers/spaces.ts @@ -158,6 +158,24 @@ async function loadSpacesMetrics() { mapSpaces(); } +export async function getSpace(id: string) { + const query = ` + SELECT settings, flagged, verified + FROM spaces + WHERE deleted = 0 AND id = ? + LIMIT 1`; + + const [space] = await db.queryAsync(query, [id]); + + if (!space) return Promise.reject(new Error('NOT_FOUND')); + + return { + ...JSON.parse(space.settings), + flagged: space.flagged === 1, + verified: space.verified === 1 + }; +} + async function run() { try { await loadSpaces(); diff --git a/test/e2e/space.test.ts b/test/e2e/space.test.ts index 32255348..1747d41f 100644 --- a/test/e2e/space.test.ts +++ b/test/e2e/space.test.ts @@ -1,9 +1,60 @@ +import fetch from 'node-fetch'; +import db from '../../src/helpers/mysql'; +import fixtures from '../fixtures/spaces'; + +const HOST = `http://localhost:${process.env.PORT || 3030}`; + describe('GET /api/space/:key', () => { + beforeAll(async () => { + await db.queryAsync('DELETE from spaces'); + await Promise.all( + fixtures.map(f => { + return db.queryAsync('INSERT INTO spaces SET ?', { + ...f, + settings: JSON.stringify(f.settings) + }); + }) + ); + }); + + afterAll(async () => { + await db.queryAsync('DELETE from spaces'); + await db.endAsync(); + }); + describe('when the space exists', () => { - it.todo('returns a space object'); + let response; + beforeAll(async () => { + response = await fetch(`${HOST}/api/spaces/fabien.eth`); + }); + + it('returns the correct HTTP response', () => { + expect(response.status); + expect(response.headers.get('content-type')).toContain('application/json'); + }); + + it('returns the space data', async () => { + const space = fixtures[0]; + const expectedSpace = { + flagged: space.flagged, + verified: space.verified, + ...space.settings + }; + + expect(response.json()).resolves.toEqual(expectedSpace); + }); }); describe('when the space does not exist', () => { - it.todo('returns a 404 error'); + it('returns a 404 error', async () => { + const response = await fetch(`${HOST}/api/spaces/null.eth`); + + expect(response.status).toBe(404); + expect(response.headers.get('content-type')).toContain('application/json'); + expect(response.json()).resolves.toEqual({ + error: 'unauthorized', + error_description: 'not_found' + }); + }); }); }); diff --git a/test/fixtures/spaces.ts b/test/fixtures/spaces.ts new file mode 100644 index 00000000..a917f972 --- /dev/null +++ b/test/fixtures/spaces.ts @@ -0,0 +1,13 @@ +const fixtures: Record[] = [ + { + id: 'fabien.eth', + name: 'Fabien.eth', + flagged: false, + verified: true, + settings: { network: 1 }, + created_at: Math.floor(Date.now() / 1e3), + updated_at: Math.floor(Date.now() / 1e3) + } +]; + +export default fixtures; diff --git a/yarn.lock b/yarn.lock index c4ce8cc0..d736f55f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1779,11 +1779,6 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -asap@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - async@^3.2.3: version "3.2.4" resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" @@ -2171,11 +2166,6 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -component-emitter@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2223,11 +2213,6 @@ cookie@^0.4.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== -cookiejar@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" - integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== - copyfiles@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.4.1.tgz#d2dcff60aaad1015f09d0b66e7f0f1c5cd3c5da5" @@ -2374,14 +2359,6 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== -dezalgo@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" - integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== - dependencies: - asap "^2.0.0" - wrappy "1" - diff-sequences@^29.4.3: version "29.4.3" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" @@ -2925,11 +2902,6 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== -fast-safe-stringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - fastq@^1.6.0: version "1.11.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.0.tgz#bb9fb955a07130a918eb63c1f5161cc32a5d0858" @@ -3031,16 +3003,6 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -formidable@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.1.2.tgz#fa973a2bec150e4ce7cac15589d7a25fc30ebd89" - integrity sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g== - dependencies: - dezalgo "^1.0.4" - hexoid "^1.0.0" - once "^1.4.0" - qs "^6.11.0" - forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -3310,11 +3272,6 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hexoid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" - integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== - hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -4297,7 +4254,7 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -methods@^1.1.2, methods@~1.1.2: +methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= @@ -4339,11 +4296,6 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -4423,7 +4375,7 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -node-fetch@^2.6.11, node-fetch@^2.7.0: +node-fetch@^2.6.11, node-fetch@^2.7, node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -4555,7 +4507,7 @@ on-finished@2.4.1, on-finished@^2.3.0: dependencies: ee-first "1.1.1" -once@^1.3.0, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -4812,13 +4764,6 @@ qs@6.10.3: dependencies: side-channel "^1.0.4" -qs@^6.11.0: - version "6.11.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" - integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== - dependencies: - side-channel "^1.0.4" - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -5074,7 +5019,7 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: +semver@^7.5.3, semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -5343,30 +5288,6 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -superagent@^8.0.5: - version "8.0.9" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.0.9.tgz#2c6fda6fadb40516515f93e9098c0eb1602e0535" - integrity sha512-4C7Bh5pyHTvU33KpZgwrNKh/VQnvgtCSqPRfJAUdmrtSYePVzVg4E4OzsrbkhJj9O7SO6Bnv75K/F8XVZT8YHA== - dependencies: - component-emitter "^1.3.0" - cookiejar "^2.1.4" - debug "^4.3.4" - fast-safe-stringify "^2.1.1" - form-data "^4.0.0" - formidable "^2.1.2" - methods "^1.1.2" - mime "2.6.0" - qs "^6.11.0" - semver "^7.3.8" - -supertest@^6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.3.3.tgz#42f4da199fee656106fd422c094cf6c9578141db" - integrity sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA== - dependencies: - methods "^1.1.2" - superagent "^8.0.5" - supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"