Clear active role if no longer in available roles (#7345)

* if role is removed from user, reprompt

* add some basic user login tests

* add more robust user tests

* add more robust user tests

* resolve PR comments

* setup event listener earlier
This commit is contained in:
Scott Bell 2024-01-16 17:57:57 +01:00 committed by GitHub
parent 11f3ce9470
commit 70f5ba9ca8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 91 additions and 8 deletions

View File

@ -0,0 +1,69 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2023, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
import { fileURLToPath } from 'url';
import { expect, test } from '../../pluginFixtures.js';
test.describe('User Roles', () => {
test('Role prompting', async ({ page }) => {
await page.addInitScript({
path: fileURLToPath(new URL('../../helper/addInitExampleUser.js', import.meta.url))
});
await page.goto('./', { waitUntil: 'domcontentloaded' });
// we have multiple available roles, so it should prompt the user
await expect(page.getByText('Select Role')).toBeVisible();
await page.getByRole('combobox').selectOption('driver');
await page.getByRole('button', { name: 'Select' }).click();
await expect(page.getByLabel('User Role')).toContainText('driver');
// attempt changing the role to another valid available role
await page.getByRole('button', { name: 'Change Role' }).click();
await page.getByRole('combobox').selectOption('flight');
await page.getByRole('button', { name: 'Select' }).click();
await expect(page.getByLabel('User Role')).toContainText('flight');
// reload page
await page.reload({ waitUntil: 'domcontentloaded' });
// should still be logged in as flight, and tell the user as much
await expect(page.getByLabel('User Role')).toContainText('flight');
await expect(page.getByText("You're logged in as role flight")).toBeVisible();
// change active role in local storage to "apple_role", a bogus role not in the list of available roles
await page.evaluate(() => {
const openmct = window.openmct;
openmct.user.setActiveRole('apple_role');
});
// reload page
await page.reload({ waitUntil: 'domcontentloaded' });
// verify that role is prompted
await expect(page.getByText('Select Role')).toBeVisible();
// select real role of "driver"
await page.getByRole('combobox').selectOption('driver');
await page.getByRole('button', { name: 'Select' }).click();
await expect(page.getByLabel('User Role')).toContainText('driver');
});
});

View File

@ -123,7 +123,11 @@ class UserAPI extends EventEmitter {
* @returns {undefined}
*/
setActiveRole(role) {
if (!role) {
StoragePersistance.clearActiveRole();
} else {
StoragePersistance.setActiveRole(role);
}
this.emit('roleChanged', role);
}

View File

@ -22,7 +22,7 @@
<template>
<div class="c-indicator icon-person c-indicator--clickable">
<span class="label c-indicator__label">
<span class="label c-indicator__label" aria-label="User Role">
{{ role ? `${userName}: ${role}` : userName }}
<button v-if="availableRoles?.length > 1" @click="promptForRoleSelection">Change Role</button>
</span>
@ -45,38 +45,48 @@ export default {
},
async mounted() {
// need to wait for openmct to be loaded before using openmct.overlays.selection
// as document.body could be null
this.openmct.on('start', this.fetchOrPromptForRole);
await this.getUserInfo();
this.roleChannel = new ActiveRoleSynchronizer(this.openmct);
this.roleChannel.subscribeToRoleChanges(this.onRoleChange);
await this.fetchOrPromptForRole();
},
beforeUnmount() {
this.roleChannel.unsubscribeFromRoleChanges(this.onRoleChange);
this.openmct.off('start', this.fetchOrPromptForRole);
},
methods: {
async getUserInfo() {
const user = await this.openmct.user.getCurrentUser();
this.userName = user.getName();
this.role = this.openmct.user.getActiveRole();
this.availableRoles = await this.openmct.user.getPossibleRoles();
this.loggedIn = this.openmct.user.isLoggedIn();
},
async fetchOrPromptForRole() {
const UserAPI = this.openmct.user;
const activeRole = UserAPI.getActiveRole();
this.role = activeRole;
if (!activeRole) {
this.availableRoles = await this.openmct.user.getPossibleRoles();
// clear role if it's not in list of available roles, e.g., removed by admin
if (!this.availableRoles?.includes(this.role)) {
this.role = null;
UserAPI.setActiveRole(null);
}
// see if we need to prompt for role selection
if (!this.role) {
this.promptForRoleSelection();
} else {
// only notify the user if they have more than one role available
this.availableRoles = await this.openmct.user.getPossibleRoles();
if (this.availableRoles.length > 1) {
this.openmct.notifications.info(`You're logged in as role ${activeRole}`);
}
}
},
async promptForRoleSelection() {
this.availableRoles = await this.openmct.user.getPossibleRoles();
promptForRoleSelection() {
const selectionOptions = this.availableRoles.map((role) => ({
key: role,
name: role