- Upload a profile picture on web and mobile. The API square-crops it to 512px WebP, strips metadata (phone photos carry GPS), stores it in Postgres and serves it with immutable caching. Avatar URLs are stored as paths, so they survive moving the API. Arbitrary avatar URLs are no longer accepted (they'd let a profile track its viewers). - New accounts get the username as typed as their display name; existing accounts are backfilled, and clearing it falls back to the username. - Service names in Settings get a brand-coloured badge and larger type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MzFywujuH9TiuXbr9vjoX8
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import sharp from 'sharp';
|
||||
import { env } from '../env';
|
||||
import { HttpError } from './http';
|
||||
|
||||
export const AVATAR_SIZE = 512;
|
||||
export const AVATAR_MAX_UPLOAD_BYTES = 10 * 1024 * 1024;
|
||||
|
||||
/**
|
||||
* Uploaded avatars are stored as a path (`/avatars/<id>?v=<version>`) so they keep
|
||||
* working if the API moves; older rows may hold a full external URL.
|
||||
*/
|
||||
export const publicAvatarUrl = (stored: string | null): string | null =>
|
||||
stored?.startsWith('/') ? env.API_PUBLIC_URL.replace(/\/$/, '') + stored : stored;
|
||||
|
||||
/**
|
||||
* Square-crops, resizes and re-encodes to WebP. Re-encoding also drops EXIF
|
||||
* (phone photos carry GPS location) and anything that isn't image data.
|
||||
*/
|
||||
export async function processAvatar(input: Buffer): Promise<Buffer> {
|
||||
try {
|
||||
return await sharp(input, { limitInputPixels: 50_000_000, animated: false })
|
||||
.rotate() // apply the EXIF orientation before it's stripped
|
||||
.resize(AVATAR_SIZE, AVATAR_SIZE, { fit: 'cover', position: 'attention' })
|
||||
.webp({ quality: 82 })
|
||||
.toBuffer();
|
||||
} catch {
|
||||
throw new HttpError(400, "That file isn't an image we can read. Try a JPEG, PNG, WebP or HEIC.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user