diff --git a/pages/player/[id]/index.js b/pages/player/[id]/index.js index 131e8c75f..0a4dc2f3b 100644 --- a/pages/player/[id]/index.js +++ b/pages/player/[id]/index.js @@ -20,7 +20,7 @@ import PlayerActions from '../../../components/player/PlayerActions' import PlayerLastSeen from '../../../components/player/PlayerLastSeen' export async function getServerSideProps ({ req, params }) { - const { isUUID } = require('validator') + const { isUUID } = require('../../../server/data/uuid') if (!isUUID(params.id)) return { notFound: true } diff --git a/server/data/uuid.js b/server/data/uuid.js new file mode 100644 index 000000000..bd3c66dbb --- /dev/null +++ b/server/data/uuid.js @@ -0,0 +1,8 @@ +const { isUUID: validatorIsUUID } = require('validator') + +// Wrapper around validator's isUUID with 'loose' mode to support Bedrock/Floodgate UUIDs +// Standard isUUID rejects non-RFC 4122 compliant UUIDs (version/variant bits) +// Bedrock UUIDs typically have format: 00000000-0000-0000-XXXX-XXXXXXXXXXXX +const isUUID = (str) => validatorIsUUID(str, 'loose') + +module.exports = { isUUID } diff --git a/server/graphql/resolvers/scalars/uuid.js b/server/graphql/resolvers/scalars/uuid.js index 297679677..f4aa72a44 100644 --- a/server/graphql/resolvers/scalars/uuid.js +++ b/server/graphql/resolvers/scalars/uuid.js @@ -1,8 +1,8 @@ const { parse, unparse } = require('uuid-parse') const { GraphQLScalarType } = require('graphql') const { Kind } = require('graphql/language') -const { isUUID } = require('validator') const ExposedErrpr = require('../../../data/exposed-error') +const { isUUID } = require('../../../data/uuid') module.exports = new GraphQLScalarType( { diff --git a/server/routes/opengraph/player.js b/server/routes/opengraph/player.js index 233c1ad33..b1e992855 100644 --- a/server/routes/opengraph/player.js +++ b/server/routes/opengraph/player.js @@ -1,5 +1,5 @@ -const { isUUID } = require('validator') const { parse } = require('uuid-parse') +const { isUUID } = require('../../data/uuid') const path = require('path') const sharp = require('sharp') const send = require('koa-send') diff --git a/server/test/player.query.test.js b/server/test/player.query.test.js index a753d75ba..61680953f 100644 --- a/server/test/player.query.test.js +++ b/server/test/player.query.test.js @@ -1,5 +1,5 @@ const assert = require('assert') -const { unparse } = require('uuid-parse') +const { parse, unparse } = require('uuid-parse') const supertest = require('supertest') const createApp = require('../app') const { createSetup } = require('./lib') @@ -49,4 +49,37 @@ describe('Query player', () => { assert.strictEqual(body.data.player.name, player.name) assert.strictEqual(body.data.player.lastSeen, player.lastSeen) }) + + test('should resolve Bedrock/Floodgate UUID format', async () => { + const { pool } = setup.serversPool.values().next().value + + const bedrockUUID = '00000000-0000-0000-0009-01f4bf5b7415' + const player = createPlayer({ + id: parse(bedrockUUID, Buffer.alloc(16)) + }) + + await pool('bm_players').insert(player) + + const { body, statusCode } = await request + .post('/graphql') + .set('Accept', 'application/json') + .send({ + query: `query players { + player(player:"${bedrockUUID}") { + id + name + lastSeen + } + }` + }) + + assert.strictEqual(statusCode, 200) + + assert(body) + assert(body.data) + + assert.strictEqual(body.data.player.id, bedrockUUID) + assert.strictEqual(body.data.player.name, player.name) + assert.strictEqual(body.data.player.lastSeen, player.lastSeen) + }) })