From 332f1c4544d032c941e896300a1382e831542cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Tue, 20 Apr 2021 09:58:23 +0200 Subject: [PATCH] feat: expose user permissions (#791) --- src/lib/routes/admin-api/user.js | 37 ------------------ src/lib/routes/admin-api/user.test.js | 31 +++++++++------ src/lib/routes/admin-api/user.ts | 52 ++++++++++++++++++++++++++ src/lib/routes/unleash-types.ts | 2 + src/test/fixtures/fake-access-store.ts | 2 +- 5 files changed, 74 insertions(+), 50 deletions(-) delete mode 100644 src/lib/routes/admin-api/user.js create mode 100644 src/lib/routes/admin-api/user.ts diff --git a/src/lib/routes/admin-api/user.js b/src/lib/routes/admin-api/user.js deleted file mode 100644 index 31f7681c8c..0000000000 --- a/src/lib/routes/admin-api/user.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -const Controller = require('../controller'); - -class UserController extends Controller { - constructor(config) { - super(config); - this.logger = config.getLogger('admin-api/user.js'); - this.get('/', this.getUser); - this.get('/logout', this.logout); - } - - getUser(req, res) { - if (req.user) { - const user = { ...req.user }; - delete user.permissions; // TODO: remove - return res - .status(200) - .json(user) - .end(); - } - return res.status(404).end(); - } - - // Deprecated, use "/logout" instead. Will be removed in v4. - logout(req, res) { - if (req.session) { - req.session = null; - } - if (req.logout) { - req.logout(); - } - res.redirect(`${this.config.baseUriPath}/`); - } -} - -module.exports = UserController; diff --git a/src/lib/routes/admin-api/user.test.js b/src/lib/routes/admin-api/user.test.js index f05eef122f..cacb3d89ed 100644 --- a/src/lib/routes/admin-api/user.test.js +++ b/src/lib/routes/admin-api/user.test.js @@ -12,21 +12,28 @@ const eventBus = new EventEmitter(); const currentUser = new User({ email: 'test@mail.com' }); +const fakeAccessService = { + getPermissionsForUser: () => [], +}; + function getSetup() { const base = `/random${Math.round(Math.random() * 1000)}`; const stores = store.createStores(); - const app = getApp({ - baseUriPath: base, - stores, - eventBus, - getLogger, - preHook: a => { - a.use((req, res, next) => { - req.user = currentUser; - next(); - }); + const app = getApp( + { + baseUriPath: base, + stores, + eventBus, + getLogger, + preHook: a => { + a.use((req, res, next) => { + req.user = currentUser; + next(); + }); + }, }, - }); + { accessService: fakeAccessService }, + ); return { base, @@ -44,7 +51,7 @@ test('should return current user', t => { .expect(200) .expect('Content-Type', /json/) .expect(res => { - t.true(res.body.email === currentUser.email); + t.true(res.body.user.email === currentUser.email); }); }); diff --git a/src/lib/routes/admin-api/user.ts b/src/lib/routes/admin-api/user.ts new file mode 100644 index 0000000000..f18faf3fe5 --- /dev/null +++ b/src/lib/routes/admin-api/user.ts @@ -0,0 +1,52 @@ +'use strict'; + +import { Response } from 'express'; +import { IUnleashConfig } from '../../types/core'; +import { IAuthRequest } from '../unleash-types'; +import Controller from '../controller'; +import { AccessService } from '../../services/access-service'; + +interface IService { + accessService: AccessService; +} + +class UserController extends Controller { + private accessService: AccessService; + + constructor(config: IUnleashConfig, { accessService }: IService) { + super(config); + this.accessService = accessService; + + this.get('/', this.getUser); + this.get('/logout', this.logout); + } + + async getUser(req: IAuthRequest, res: Response): Promise { + const { user } = req; + if (user) { + const permissions = await this.accessService.getPermissionsForUser( + user, + ); + delete user.permissions; // TODO: remove + return res + .status(200) + .json({ user, permissions }) + .end(); + } + return res.status(404).end(); + } + + // Deprecated, use "/logout" instead. Will be removed in v4. + logout(req: IAuthRequest, res: Response): void { + if (req.session) { + req.session = null; + } + if (req.logout) { + req.logout(); + } + res.redirect(`${this.config.baseUriPath}/`); + } +} + +module.exports = UserController; +export default UserController; diff --git a/src/lib/routes/unleash-types.ts b/src/lib/routes/unleash-types.ts index 03b54bcfc8..2b9c5e1d5c 100644 --- a/src/lib/routes/unleash-types.ts +++ b/src/lib/routes/unleash-types.ts @@ -3,4 +3,6 @@ import User from '../user'; export interface IAuthRequest extends Request { user: User; + logout: () => void; + session: any; } diff --git a/src/test/fixtures/fake-access-store.ts b/src/test/fixtures/fake-access-store.ts index c3aac27aa9..2f71b0e6b7 100644 --- a/src/test/fixtures/fake-access-store.ts +++ b/src/test/fixtures/fake-access-store.ts @@ -13,7 +13,7 @@ class AccessStoreMock extends AccessStore { } getPermissionsForUser(userId: Number): Promise { - throw new Error('Method not implemented.'); + return Promise.resolve([]); } getPermissionsForRole(roleId: number): Promise {