Merge pull request 'feat: add first_name and last_name fields to UserTenant model and sync with Keycloak' (#366) from fix/user-profile-edit-keycloak-sync into development
Reviewed-on: ADUANASOFT/anexo76#366
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { getContext, onMount } from "svelte";
|
||||
import { onMount } from "svelte";
|
||||
import { page } from "$app/state";
|
||||
import { useSidebar } from "$lib/components/ui/sidebar/context.svelte.js";
|
||||
import { getSidebarData } from "$lib/components/sidebar/modules";
|
||||
import NavMain from "./nav-main.svelte";
|
||||
@@ -15,9 +16,8 @@
|
||||
...restProps
|
||||
}: ComponentProps<typeof Sidebar.Root> = $props();
|
||||
|
||||
// Obtener datos del usuario desde el contexto (viene de Keycloak vía +layout.server.ts)
|
||||
const userData = getContext<any>('user');
|
||||
const userTenants = getContext<{ id: number; name: string; slug: string }[]>('userTenants') ?? [];
|
||||
// Leer siempre de page.data para que el sidebar reaccione tras invalidateAll()
|
||||
const userTenants = $derived((page.data.userTenants as { id: number; name: string; slug: string }[]) ?? []);
|
||||
|
||||
// Obtener datos del sidebar con traducciones
|
||||
const sidebarData = getSidebarData();
|
||||
@@ -25,15 +25,21 @@
|
||||
// Combinar los datos estáticos del sidebar con los datos del usuario de Keycloak
|
||||
const data = $derived({
|
||||
...sidebarData,
|
||||
user: userData
|
||||
user: page.data.user
|
||||
? {
|
||||
name: userData.name || userData.preferred_username || "",
|
||||
email: userData.email || "",
|
||||
avatar: userData.avatar_url || "/avatars/default.jpg",
|
||||
name: _displayName(page.data.user),
|
||||
email: page.data.user.email || "",
|
||||
avatar: page.data.user.avatar_url || "/avatars/default.jpg",
|
||||
}
|
||||
: sidebarData.user,
|
||||
});
|
||||
|
||||
function _displayName(u: any): string {
|
||||
const first = u.first_name || u.given_name || "";
|
||||
const last = u.last_name || u.family_name || "";
|
||||
return (first + " " + last).trim() || u.name || u.preferred_username || "";
|
||||
}
|
||||
|
||||
const sidebar = useSidebar();
|
||||
|
||||
onMount(() => {
|
||||
|
||||
@@ -285,20 +285,34 @@ export async function validateAuth(
|
||||
|
||||
if (profileResponse.ok) {
|
||||
const profileData = await profileResponse.json();
|
||||
// Combinar datos de Keycloak con datos del perfil
|
||||
// Combinar datos de Keycloak con datos del perfil.
|
||||
// Prioridad para nombre: caché local del perfil > JWT claims.
|
||||
return {
|
||||
...keycloakData,
|
||||
avatar_url: profileData.avatar_url,
|
||||
phone: profileData.phone,
|
||||
bio: profileData.bio,
|
||||
preferences: profileData.preferences
|
||||
id: profileData.id || keycloakData.id || keycloakData.sub,
|
||||
username: profileData.username || keycloakData.username || keycloakData.preferred_username || '',
|
||||
email: profileData.email || keycloakData.email || '',
|
||||
first_name: profileData.first_name || keycloakData.first_name || keycloakData.given_name || '',
|
||||
last_name: profileData.last_name || keycloakData.last_name || keycloakData.family_name || '',
|
||||
avatar_url: profileData.avatar_url || null,
|
||||
phone: profileData.phone || null,
|
||||
bio: profileData.bio || null,
|
||||
preferences: profileData.preferences || {}
|
||||
};
|
||||
}
|
||||
} catch (profileError) {
|
||||
console.warn('⚠️ [API] No se pudo cargar el perfil del usuario, usando solo datos de Keycloak');
|
||||
}
|
||||
|
||||
return keycloakData;
|
||||
// Fallback: map raw JWT claim names to the expected field names
|
||||
const nameParts = (keycloakData.name || '').split(' ');
|
||||
return {
|
||||
...keycloakData,
|
||||
id: keycloakData.id || keycloakData.sub,
|
||||
username: keycloakData.username || keycloakData.preferred_username || '',
|
||||
first_name: keycloakData.first_name || keycloakData.given_name || nameParts[0] || '',
|
||||
last_name: keycloakData.last_name || keycloakData.family_name || nameParts.slice(1).join(' ') || '',
|
||||
};
|
||||
} catch (error) {
|
||||
// Si es un redirect, re-lanzarlo
|
||||
if (error && typeof error === 'object' && 'status' in error && 'location' in error) {
|
||||
|
||||
Reference in New Issue
Block a user