diff --git a/frontend/src/stores/auth.js b/frontend/src/stores/auth.js index a419b6b..8c91009 100644 --- a/frontend/src/stores/auth.js +++ b/frontend/src/stores/auth.js @@ -1,5 +1,5 @@ import { defineStore } from 'pinia' -import { authApi } from '../api' +import { authApi, employeesApi } from '../api' export const useAuthStore = defineStore('auth', { state: () => ({ @@ -12,7 +12,12 @@ export const useAuthStore = defineStore('auth', { username: (state) => state.user?.username || '', roles: (state) => state.user?.roles || [], hasRole: (state) => (role) => state.user?.roles?.includes(role) || false, - isAdmin: (state) => state.user?.roles?.includes('admin') || false + isAdmin: (state) => state.user?.roles?.includes('admin') || false, + // Full name from the employee directory (falls back to username/SSO). + displayName: (state) => state.user?.directoryname || state.user?.username || '', + // Employee photo URL if the directory has one for this SSO. + avatarUrl: (state) => state.user?.directorypicture + ? `/static/employees/${state.user.directorypicture}` : null }, actions: { @@ -24,9 +29,10 @@ export const useAuthStore = defineStore('auth', { this.token = access_token this.user = user + this.token = access_token localStorage.setItem('token', access_token) localStorage.setItem('refreshToken', refresh_token) - localStorage.setItem('user', JSON.stringify(user)) + await this.enrichFromDirectory() return { success: true } } catch (error) { @@ -54,10 +60,28 @@ export const useAuthStore = defineStore('auth', { try { const response = await authApi.me() this.user = response.data.data - localStorage.setItem('user', JSON.stringify(this.user)) + await this.enrichFromDirectory() } catch (error) { this.logout() } + }, + + // Pull the logged-in user's full name + photo from the employee directory + // by their SSO (= username). Best-effort: skipped/ignored when the employees + // plugin is off, the SSO is not in the directory, or the lookup fails. + async enrichFromDirectory() { + const sso = this.user?.username + if (sso && /^\d+$/.test(sso)) { + try { + const response = await employeesApi.lookup(sso) + const emp = response.data?.data + if (emp) { + this.user.directoryname = `${emp.First_Name || ''} ${emp.Last_Name || ''}`.trim() || null + this.user.directorypicture = emp.Picture || null + } + } catch (err) { /* directory unavailable - fall back to username */ } + } + localStorage.setItem('user', JSON.stringify(this.user)) } } }) diff --git a/frontend/src/views/AppLayout.vue b/frontend/src/views/AppLayout.vue index 37ed1bc..abdcfc8 100644 --- a/frontend/src/views/AppLayout.vue +++ b/frontend/src/views/AppLayout.vue @@ -39,7 +39,12 @@
Login @@ -196,4 +201,16 @@ async function handleLogout() { await authStore.logout() router.push('/login') } + +// Hide a broken avatar (photo filename set but file missing). +function onAvatarError(event) { + event.target.style.display = 'none' +} + +