fix(federation): store absolute URLs for replicated user avatars

Bare filenames stored on replicated user stubs can't be resolved by
the home WS (normalizeUserAssets only runs for remote origins).
Now resolves avatar/banner to absolute URLs pointing to the user's
home instance so they render correctly without page refresh.
Also overwrites stale bare filenames from the prior deploy.
This commit is contained in:
Jannis Braun
2026-03-27 01:36:23 +01:00
parent 699c5a4365
commit 843a2ce727
+12 -2
View File
@@ -1872,11 +1872,21 @@ function hydrateReplicatedUserProfile(
if (!profile) return user; if (!profile) return user;
if (!user.homeInstance) return user; // Don't update native users if (!user.homeInstance) return user; // Don't update native users
// Resolve bare filenames to absolute URLs pointing to the home instance.
// The home WS doesn't run normalizeUserAssets on replicated users' avatars,
// so they must be stored as absolute URLs to render correctly.
const resolveUrl = (filename: string | null | undefined): string | null => {
if (!filename) return null;
if (filename.startsWith('http')) return filename;
return `${user.homeInstance}/api/uploads/${filename}`;
};
const updates: Record<string, string | null> = {}; const updates: Record<string, string | null> = {};
if (profile.displayName && !user.displayName) updates.displayName = profile.displayName; if (profile.displayName && !user.displayName) updates.displayName = profile.displayName;
if (profile.avatar && !user.avatar) updates.avatar = profile.avatar; // Overwrite avatar/banner if missing OR if it's a stale bare filename (not an absolute URL)
if (profile.avatar && (!user.avatar || !user.avatar.startsWith('http'))) updates.avatar = resolveUrl(profile.avatar);
if (profile.avatarColor && !user.avatarColor) updates.avatarColor = profile.avatarColor; if (profile.avatarColor && !user.avatarColor) updates.avatarColor = profile.avatarColor;
if (profile.banner && !user.banner) updates.banner = profile.banner; if (profile.banner && (!user.banner || !user.banner.startsWith('http'))) updates.banner = resolveUrl(profile.banner);
if (profile.bio && !user.bio) updates.bio = profile.bio; if (profile.bio && !user.bio) updates.bio = profile.bio;
if (Object.keys(updates).length === 0) return user; if (Object.keys(updates).length === 0) return user;