diff --git a/test/api/v3/integration/hall/GET-hall_heroes_heroId.test.js b/test/api/v3/integration/hall/GET-hall_heroes_heroId.test.js index b687ee0ed9..b2d7bc6383 100644 --- a/test/api/v3/integration/hall/GET-hall_heroes_heroId.test.js +++ b/test/api/v3/integration/hall/GET-hall_heroes_heroId.test.js @@ -25,9 +25,9 @@ describe('GET /heroes/:heroId', () => { it('validates req.params.heroId', async () => { await expect(user.get('/hall/heroes/invalidUUID')).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('invalidReqParams'), + code: 404, + error: 'NotFound', + message: t('userWithIDNotFound', {userId: 'invalidUUID'}), }); }); @@ -40,7 +40,7 @@ describe('GET /heroes/:heroId', () => { }); }); - it('returns only necessary hero data', async () => { + it('returns only necessary hero data given user id', async () => { let hero = await generateUser({ contributor: {tier: 23}, }); @@ -53,4 +53,18 @@ describe('GET /heroes/:heroId', () => { expect(heroRes.auth.local).not.to.have.keys(['salt', 'hashed_password']); expect(heroRes.profile).to.have.all.keys(['name']); }); + + it('returns only necessary hero data given username', async () => { + let hero = await generateUser({ + contributor: {tier: 23}, + }); + let heroRes = await user.get(`/hall/heroes/${hero.auth.local.username}`); + + expect(heroRes).to.have.all.keys([ // works as: object has all and only these keys + '_id', 'id', 'balance', 'profile', 'purchased', + 'contributor', 'auth', 'items', + ]); + expect(heroRes.auth.local).not.to.have.keys(['salt', 'hashed_password']); + expect(heroRes.profile).to.have.all.keys(['name']); + }); }); diff --git a/website/client/components/hall/heroes.vue b/website/client/components/hall/heroes.vue index 391a031657..6f62783132 100644 --- a/website/client/components/hall/heroes.vue +++ b/website/client/components/hall/heroes.vue @@ -8,7 +8,7 @@ .row .form.col-6(v-if='!hero.profile') .form-group - input.form-control(type='text', v-model='heroID', :placeholder="$t('UUID')") + input.form-control(type='text', v-model='heroID', :placeholder="'User ID or Username'") .form-group button.btn.btn-secondary(@click='loadHero(heroID)') | {{ $t('loadUser') }} diff --git a/website/server/controllers/api-v3/hall.js b/website/server/controllers/api-v3/hall.js index 21dfdadbb0..e42adb80c5 100644 --- a/website/server/controllers/api-v3/hall.js +++ b/website/server/controllers/api-v3/hall.js @@ -6,6 +6,7 @@ import { } from '../../libs/errors'; import _ from 'lodash'; import apiError from '../../libs/apiError'; +import validator from 'validator'; let api = {}; @@ -142,7 +143,7 @@ api.getHeroes = { const heroAdminFields = 'contributor balance profile.name purchased items auth flags.chatRevoked'; /** - * @api {get} /api/v3/hall/heroes/:heroId Get any user ("hero") given the UUID + * @api {get} /api/v3/hall/heroes/:heroId Get any user ("hero") given the UUID or Username * @apiParam (Path) {UUID} heroId user ID * @apiName GetHero * @apiGroup Hall @@ -162,15 +163,23 @@ api.getHero = { url: '/hall/heroes/:heroId', middlewares: [authWithHeaders(), ensureAdmin], async handler (req, res) { - let heroId = req.params.heroId; + let validationErrors; + req.checkParams('heroId', res.t('heroIdRequired')).notEmpty(); - req.checkParams('heroId', res.t('heroIdRequired')).notEmpty().isUUID(); - - let validationErrors = req.validationErrors(); + validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; - let hero = await User - .findById(heroId) + const heroId = req.params.heroId; + + let query; + if (validator.isUUID(heroId)) { + query = {_id: heroId}; + } else { + query = {'auth.local.username': heroId}; + } + + const hero = await User + .findOne(query) .select(heroAdminFields) .exec();