mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
49 lines
2.0 KiB
JavaScript
49 lines
2.0 KiB
JavaScript
// utils/resolveAvatar.util.js
|
|
//
|
|
// Resolves a stored avatar into a browser-usable URL at read time.
|
|
//
|
|
// personal_info.avatar.url is never trustworthy as stored:
|
|
// - S3-stored avatars (avatar.uuid present) were historically saved with a
|
|
// raw, unsigned bucket URL (see s3.service.js buildPublicUrl). The current
|
|
// Garage ingress (Cloudflare lane, see chibistar/Caddyfile) forwards reads
|
|
// straight to Garage with no re-signing, and Garage rejects anonymous
|
|
// requests outright — so that stored URL 403s in the browser. Even a
|
|
// presigned URL would go stale if persisted (getPublicUrl() expires in 4h),
|
|
// so the only correct fix is to mint a fresh one on every read from the
|
|
// stored key (avatar.uuid), never trust what's on the row.
|
|
// - Google-picture avatars (reg_type: 'google', no uuid — see
|
|
// auth.controller.js googleCallback) are an external CDN URL and pass
|
|
// through unchanged; there's nothing of ours to sign.
|
|
//
|
|
const { getPublicUrl } = require('../services/s3.service');
|
|
|
|
async function resolveAvatarUrl(avatar) {
|
|
if (!avatar) return avatar ?? null;
|
|
if (!avatar.uuid) return avatar; // external URL (e.g. Google) — nothing to sign
|
|
|
|
try {
|
|
const url = await getPublicUrl(avatar.uuid);
|
|
return { ...avatar, url };
|
|
} catch (err) {
|
|
console.error('[AVATAR] Failed to resolve presigned URL for', avatar.uuid, err);
|
|
return avatar; // fall back to the stored value rather than failing the whole response
|
|
}
|
|
}
|
|
|
|
// Mutates-and-returns a shallow copy of a user (plain object or Sequelize
|
|
// instance) with personal_info.avatar resolved. Safe to call on a user with
|
|
// no avatar at all.
|
|
async function resolveUserAvatar(user) {
|
|
if (!user) return user;
|
|
const u = user.toJSON ? user.toJSON() : { ...user };
|
|
if (!u.personal_info?.avatar) return u;
|
|
|
|
u.personal_info = {
|
|
...u.personal_info,
|
|
avatar: await resolveAvatarUrl(u.personal_info.avatar),
|
|
};
|
|
return u;
|
|
}
|
|
|
|
module.exports = { resolveAvatarUrl, resolveUserAvatar };
|