From 05ea9685b095931577d20b1551f7d09937e54f52 Mon Sep 17 00:00:00 2001 From: jannyHou Date: Wed, 25 Sep 2019 15:39:05 -0400 Subject: [PATCH] fix: user profile to principal --- .../src/__tests__/unit/util.test.ts | 26 +++++++++++++++++++ .../src/authorize-interceptor.ts | 21 +++------------ packages/authorization/src/util.ts | 24 +++++++++++++++++ 3 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 packages/authorization/src/__tests__/unit/util.test.ts create mode 100644 packages/authorization/src/util.ts diff --git a/packages/authorization/src/__tests__/unit/util.test.ts b/packages/authorization/src/__tests__/unit/util.test.ts new file mode 100644 index 000000000000..f72c308b279a --- /dev/null +++ b/packages/authorization/src/__tests__/unit/util.test.ts @@ -0,0 +1,26 @@ +// Copyright IBM Corp. 2019. All Rights Reserved. +// Node module: @loopback/authorization +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +import {Principal, securityId, UserProfile} from '@loopback/security'; +import {expect} from '@loopback/testlab'; +import {createPrincipalFromUserProfile} from '../../util'; + +describe('utils', () => { + it('generates the correct principal', () => { + const userProfile: UserProfile = { + [securityId]: 'auser', + email: 'test@fake.com', + }; + const expectedPrincipal: Principal = { + [securityId]: 'auser', + email: 'test@fake.com', + name: 'auser', + type: 'USER', + }; + expect(createPrincipalFromUserProfile(userProfile)).to.deepEqual( + expectedPrincipal, + ); + }); +}); diff --git a/packages/authorization/src/authorize-interceptor.ts b/packages/authorization/src/authorize-interceptor.ts index ef2f5cf05d1c..cd325a63327c 100644 --- a/packages/authorization/src/authorize-interceptor.ts +++ b/packages/authorization/src/authorize-interceptor.ts @@ -17,12 +17,7 @@ import { Next, Provider, } from '@loopback/context'; -import { - Principal, - SecurityBindings, - securityId, - UserProfile, -} from '@loopback/security'; +import {SecurityBindings, UserProfile} from '@loopback/security'; import * as debugFactory from 'debug'; import {getAuthorizationMetadata} from './decorators/authorize'; import {AuthorizationBindings, AuthorizationTags} from './keys'; @@ -33,6 +28,7 @@ import { AuthorizationOptions, Authorizer, } from './types'; +import {createPrincipalFromUserProfile} from './util'; const debug = debugFactory('loopback:authorization:interceptor'); @@ -83,7 +79,7 @@ export class AuthorizationInterceptor implements Provider { debug('Current user', user); const authorizationCtx: AuthorizationContext = { - principals: user ? [userToPrinciple(user)] : [], + principals: user ? [createPrincipalFromUserProfile(user)] : [], roles: [], scopes: [], resource: invocationCtx.targetName, @@ -151,14 +147,3 @@ async function loadAuthorizers( } return authorizerFunctions; } - -// This is a workaround before we extract a common layer -// for authentication and authorization. -function userToPrinciple(user: UserProfile): Principal { - return { - name: user.name || user[securityId], - [securityId]: user.id, - email: user.email, - type: 'USER', - }; -} diff --git a/packages/authorization/src/util.ts b/packages/authorization/src/util.ts new file mode 100644 index 000000000000..c2d3849cf2f5 --- /dev/null +++ b/packages/authorization/src/util.ts @@ -0,0 +1,24 @@ +import {Principal, securityId, UserProfile} from '@loopback/security'; + +// This is a workaround before we specify `TypedPrincipal` instead of +// `Principal` for the principals in the authorization context. + +/** + * Module `@loopback/authentication` passes a user profile to + * `@loopback/authorization` as the user identity. Authorization verifies + * whether a user has access to a certain resource. + * + * The builder function: + * - preserves all the fields from user profile + * - specifies 'USER' as type + * - assign the value of `securityId` to name if it's missing in the + * user profile + * @param user The user profile passed from `@loopback/authentication`. + */ +export function createPrincipalFromUserProfile(user: UserProfile): Principal { + return { + ...user, + name: user.name || user[securityId], + type: 'USER', + }; +}