diff --git a/.gitignore b/.gitignore index c2756433b..effe34675 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.swp *.swo node_modules +.vscode/ !test/webpack/node_modules/@folio/app2/node_modules/ !test/webpack/node_modules/ npm-debug.log diff --git a/CHANGELOG.md b/CHANGELOG.md index 5378cb31f..e90776469 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * Opt-in: handle access-control via cookies. Refs STCOR-671. * Opt-in: disable login when cookies are disabled. Refs STCOR-762. * Add arial-label for `ProfileDropdown.js`. Refs STCOR-753. +* Avoid calling `map` on `undefined` via optional-chaining. Refs STCOR-793. ## [10.0.0](https://github.com/folio-org/stripes-core/tree/v10.0.0) (2023-10-11) [Full Changelog](https://github.com/folio-org/stripes-core/compare/v9.0.0...v10.0.0) diff --git a/src/components/SSOLanding.js b/src/components/SSOLanding.js index 655976178..3b0b4c397 100644 --- a/src/components/SSOLanding.js +++ b/src/components/SSOLanding.js @@ -36,14 +36,14 @@ const SSOLanding = () => { if (!token) { return ( -
ssoToken
cookie or query parameter
Logged in with token {token} from {getParams()?.ssoToken ? 'param' : 'cookie'}.
diff --git a/src/loginServices.js b/src/loginServices.js index b4d8a2c89..a86873945 100644 --- a/src/loginServices.js +++ b/src/loginServices.js @@ -397,9 +397,11 @@ export function spreadUserWithPerms(userWithPerms) { ...userWithPerms?.user?.personal, }; - // remap data's array of permission-names to set with - // permission-names for keys and `true` for values - const perms = Object.assign({}, ...userWithPerms?.permissions?.permissions.map(p => ({ [p.permissionName]: true }))); + // remap permissions from [foo, bar, bat] to { foo: true, bar: true, ... } + const perms = userWithPerms?.permissions?.permissions?.reduce((acc, i) => { + acc[i.permissionName] = true; + return acc; + }, {}); return { user, perms }; } diff --git a/test/bigtest/network/scenarios/userWithPerms.js b/test/bigtest/network/scenarios/userWithPerms.js new file mode 100644 index 000000000..81a13be16 --- /dev/null +++ b/test/bigtest/network/scenarios/userWithPerms.js @@ -0,0 +1,31 @@ +export default (server) => { + server.get('/bl-users/_self', { + 'user': { + 'username': 'diku_admin', + 'id': '882c886a-2d9a-5ffa-afc5-13912c257b99', + 'active': true, + 'patronGroup': '3684a786-6671-4268-8ed0-9db82ebca60b', + 'proxyFor': [ + ], + 'personal': { + 'lastName': 'ADMINISTRATOR', + 'firstName': 'DIKU', + 'email': 'admin@diku.example.org', + 'addresses': [ + ] + }, + 'createdDate': '2024-01-22T01:55:50.661+00:00', + 'updatedDate': '2024-01-22T01:55:50.661+00:00', + 'metadata': { + 'createdDate': '2024-01-22T01:52:08.076+00:00', + 'updatedDate': '2024-01-22T01:55:50.656+00:00', + 'updatedByUserId': '882c886a-2d9a-5ffa-afc5-13912c257b99' + }, + 'departments': [ + ] + }, + 'permissions': { + 'permissions': ['configuration.entries.collection.get'] + } + }); +}; diff --git a/test/bigtest/tests/sso-login-test.js b/test/bigtest/tests/sso-login-test.js index 640772824..e4159d38f 100644 --- a/test/bigtest/tests/sso-login-test.js +++ b/test/bigtest/tests/sso-login-test.js @@ -1,7 +1,6 @@ -import React from 'react'; import { expect } from 'chai'; -import { beforeEach, it, describe } from '@bigtest/mocha'; - +import { beforeEach, afterEach, it, describe } from '@bigtest/mocha'; +import localforage from 'localforage'; import setupApplication from '../helpers/setup-core-application'; import SSOLandingInteractor from '../interactors/SSOLanding'; @@ -18,30 +17,37 @@ describe('Login via SSO', () => { describe('SSO redirect', () => { const sso = new SSOLandingInteractor(); - describe('Renders error without token', () => { + describe('Reads token in params', () => { setupApplication({ + scenarios: ['userWithPerms'], disableAuth: false, }); + beforeEach(async function () { - this.visit('/sso-landing'); + this.visit('/sso-landing?ssoToken=c0ffee'); }); - it('Shows error message', () => { - expect(sso.isError).to.be.true; + afterEach(async () => { + await localforage.clear(); }); - it('Does not show token message', () => { - expect(sso.isValid).to.be.false; + it('Shows token message', () => { + expect(sso.isValid).to.be.true; }); }); - describe('Reads token in params', () => { + describe('Reads token in cookie', () => { setupApplication({ disableAuth: false, + cookies: { ssoToken: 'c0ffee-c0ffee' }, }); beforeEach(async function () { - this.visit('/sso-landing?ssoToken=c0ffee'); + this.visit('/sso-landing'); + }); + + afterEach(async () => { + await localforage.clear(); }); it('Shows token message', () => { @@ -49,18 +55,21 @@ describe('Login via SSO', () => { }); }); - describe('Reads token in cookie', () => { + describe('Renders error without token', () => { setupApplication({ disableAuth: false, - cookies: { ssoToken: 'c0ffee-c0ffee' }, }); beforeEach(async function () { this.visit('/sso-landing'); }); - it('Shows token message', () => { - expect(sso.isValid).to.be.true; + it('Shows error message', () => { + expect(sso.isError).to.be.true; + }); + + it('Does not show token message', () => { + expect(sso.isValid).to.be.false; }); }); });