16212: Displays user depending on available user data.
authorLucas Di Pentima <lucas@di-pentima.com.ar>
Fri, 24 Apr 2020 15:06:29 +0000 (12:06 -0300)
committerLucas Di Pentima <lucas@di-pentima.com.ar>
Wed, 29 Apr 2020 20:24:36 +0000 (17:24 -0300)
Some times first/last names or email aren't available, so we want to
show other than an empty string.

Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas@di-pentima.com.ar>

src/models/user.test.ts [new file with mode: 0644]
src/models/user.ts
src/models/vocabulary.test.ts
src/services/auth-service/auth-service.ts
src/store/auth/auth-action-session.ts
src/store/group-details-panel/group-details-panel-actions.ts
src/views-components/main-app-bar/account-menu.tsx

diff --git a/src/models/user.test.ts b/src/models/user.test.ts
new file mode 100644 (file)
index 0000000..d313ef4
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { User, getUserDisplayName } from './user';
+
+describe('User', () => {
+
+    beforeEach(() => {
+    });
+
+    it('gets the user display name', () => {
+        type UserCase = {
+            caseName: string;
+            user: User;
+            expect: string;
+        };
+        const testCases: UserCase[] = [
+            {
+                caseName: 'Full data available',
+                user: {
+                    email: 'someuser@example.com', username: 'someuser',
+                    firstName: 'Some', lastName: 'User',
+                    uuid: 'zzzzz-tpzed-someusersuuid',
+                    ownerUuid: 'zzzzz-tpzed-someusersowneruuid',
+                    prefs: {}, isAdmin: false, isActive: true
+                },
+                expect: 'Some User'
+            },
+            {
+                caseName: 'Missing first name',
+                user: {
+                    email: 'someuser@example.com', username: 'someuser',
+                    firstName: '', lastName: 'User',
+                    uuid: 'zzzzz-tpzed-someusersuuid',
+                    ownerUuid: 'zzzzz-tpzed-someusersowneruuid',
+                    prefs: {}, isAdmin: false, isActive: true
+                },
+                expect: 'someuser@example.com'
+            },
+            {
+                caseName: 'Missing last name',
+                user: {
+                    email: 'someuser@example.com', username: 'someuser',
+                    firstName: 'Some', lastName: '',
+                    uuid: 'zzzzz-tpzed-someusersuuid',
+                    ownerUuid: 'zzzzz-tpzed-someusersowneruuid',
+                    prefs: {}, isAdmin: false, isActive: true
+                },
+                expect: 'someuser@example.com'
+            },
+            {
+                caseName: 'Missing first & last names',
+                user: {
+                    email: 'someuser@example.com', username: 'someuser',
+                    firstName: '', lastName: '',
+                    uuid: 'zzzzz-tpzed-someusersuuid',
+                    ownerUuid: 'zzzzz-tpzed-someusersowneruuid',
+                    prefs: {}, isAdmin: false, isActive: true
+                },
+                expect: 'someuser@example.com'
+            },
+            {
+                caseName: 'Missing first & last names, and email address',
+                user: {
+                    email: '', username: 'someuser',
+                    firstName: '', lastName: '',
+                    uuid: 'zzzzz-tpzed-someusersuuid',
+                    ownerUuid: 'zzzzz-tpzed-someusersowneruuid',
+                    prefs: {}, isAdmin: false, isActive: true
+                },
+                expect: 'someuser'
+            },
+            {
+                caseName: 'Missing all data (should not happen)',
+                user: {
+                    email: '', username: '',
+                    firstName: '', lastName: '',
+                    uuid: 'zzzzz-tpzed-someusersuuid',
+                    ownerUuid: 'zzzzz-tpzed-someusersowneruuid',
+                    prefs: {}, isAdmin: false, isActive: true
+                },
+                expect: 'zzzzz-tpzed-someusersuuid'
+            },
+        ];
+        testCases.forEach(c => {
+            const dispName = getUserDisplayName(c.user);
+            expect(dispName).toEqual(c.expect);
+        })
+    });
+});
index 87a97dfcd1934b057369cee39bcfb82f389c05e0..1e9a026055b7b54364289a9521cdd3705cc81c9f 100644 (file)
@@ -26,8 +26,14 @@ export interface User {
     isActive: boolean;
 }
 
-export const getUserFullname = (user?: User) => {
-    return user ? `${user.firstName} ${user.lastName}` : "";
+export const getUserFullname = (user: User) => {
+    return user.firstName && user.lastName
+        ? `${user.firstName} ${user.lastName}`
+        : "";
+};
+
+export const getUserDisplayName = (user: User) => {
+    return getUserFullname(user) || user.email || user.username || user.uuid;
 };
 
 export interface UserResource extends Resource, User {
index 87a8dfb26f92688aa357318f6447203a45004cdc..18e2f19f8fe4be2e74e32af07ec5e7b4484e6308 100644 (file)
@@ -3,7 +3,6 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import * as Vocabulary from './vocabulary';
-import { pipe } from 'lodash/fp';
 
 describe('Vocabulary', () => {
     let vocabulary: Vocabulary.Vocabulary;
index 690420e78449ff35815cd63e0b1644a65012793a..61db625c62306862b6b304bfc70c8f5c9d5e4caf 100644 (file)
@@ -2,7 +2,7 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { getUserFullname, User, UserPrefs } from '~/models/user';
+import { User, UserPrefs, getUserDisplayName } from '~/models/user';
 import { AxiosInstance } from "axios";
 import { ApiActions } from "~/services/api/api-actions";
 import * as uuid from "uuid/v4";
@@ -129,7 +129,7 @@ export class AuthService {
             clusterId: cfg.uuidPrefix,
             remoteHost: cfg.rootUrl,
             baseUrl: cfg.baseUrl,
-            name: getUserFullname(user),
+            name: user ? getUserDisplayName(user): '',
             email: user ? user.email : '',
             token: this.getApiToken(),
             loggedIn: true,
index 52a1e23abf780dfbd2fab211eec79dacfa2a6e6c..fc35ff88056db1feac4ea319993b7c606a4a3631 100644 (file)
@@ -7,7 +7,7 @@ import { setBreadcrumbs } from "~/store/breadcrumbs/breadcrumbs-actions";
 import { RootState } from "~/store/store";
 import { ServiceRepository, createServices, setAuthorizationHeader } from "~/services/services";
 import Axios from "axios";
-import { getUserFullname, User } from "~/models/user";
+import { User, getUserDisplayName } from "~/models/user";
 import { authActions } from "~/store/auth/auth-action";
 import {
     Config, ClusterConfigJSON, CLUSTER_CONFIG_PATH, DISCOVERY_DOC_PATH,
@@ -131,7 +131,7 @@ export const validateSession = (session: Session, activeSession: Session) =>
             session.token = token;
             session.email = user.email;
             session.uuid = user.uuid;
-            session.name = getUserFullname(user);
+            session.name = getUserDisplayName(user);
             session.loggedIn = true;
             session.apiRevision = apiRevision;
         };
@@ -242,7 +242,7 @@ export const addSession = (remoteHost: string, token?: string, sendToLogin?: boo
                     status: SessionStatus.VALIDATED,
                     active: false,
                     email: user.email,
-                    name: getUserFullname(user),
+                    name: getUserDisplayName(user),
                     uuid: user.uuid,
                     baseUrl: config.baseUrl,
                     clusterId: config.uuidPrefix,
index 55bfd5ae8d1cef4e22079923e6e156649c370675..41fb690f2787c74e799e4edb369d7e5dbdad844e 100644 (file)
@@ -16,7 +16,7 @@ import { RootState } from '~/store/store';
 import { ServiceRepository } from '~/services/services';
 import { PermissionResource } from '~/models/permission';
 import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
-import { UserResource, getUserFullname } from '~/models/user';
+import { UserResource, getUserDisplayName } from '~/models/user';
 
 export const GROUP_DETAILS_PANEL_ID = 'groupDetailsPanel';
 export const ADD_GROUP_MEMBERS_DIALOG = 'addGrupMembers';
@@ -113,7 +113,7 @@ export const removeGroupMember = (uuid: string) =>
             await deleteGroupMember({
                 user: {
                     uuid,
-                    name: user ? getUserFullname(user) : uuid,
+                    name: user ? getUserDisplayName(user) : uuid,
                 },
                 group: {
                     uuid: groupUuid,
index 346a9ef02ea529db2fa33d4e5664ed7a567ddf40..37702536a67cc49d8a997c06f8adc41906034da8 100644 (file)
@@ -5,7 +5,7 @@
 import * as React from "react";
 import { MenuItem, Divider } from "@material-ui/core";
 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
-import { User, getUserFullname } from "~/models/user";
+import { User, getUserDisplayName } from "~/models/user";
 import { DropdownMenu } from "~/components/dropdown-menu/dropdown-menu";
 import { UserPanelIcon } from "~/components/icon/icon";
 import { DispatchProp, connect } from 'react-redux';
@@ -66,7 +66,7 @@ export const AccountMenu = withStyles(styles)(
                     title="Account Management"
                     key={currentRoute}>
                     <MenuItem disabled>
-                        {getUserFullname(user)} {user.uuid.substr(0, 5) !== localCluster && `(${user.uuid.substr(0, 5)})`}
+                        {getUserDisplayName(user)} {user.uuid.substr(0, 5) !== localCluster && `(${user.uuid.substr(0, 5)})`}
                     </MenuItem>
                     {user.isActive ? <>
                         <MenuItem onClick={() => dispatch(openUserVirtualMachines())}>Virtual Machines</MenuItem>