feat: store node logo/favicon in postgres instead of S3

- Add logoData and faviconData columns to nodes table
- Create /api/admin/node/upload endpoint for direct DB storage
- Create /api/node/logo and /api/node/favicon endpoints to serve images
- Update admin page to use new upload endpoint
- Remove dependency on admin's personal S3 storage for node assets
This commit is contained in:
Christomatt
2026-02-01 16:29:39 +01:00
parent 0cea2e9e1f
commit 90dfd62434
17 changed files with 913 additions and 90 deletions
+4 -4
View File
@@ -3,8 +3,8 @@ import { v4 as uuidv4 } from 'uuid';
export async function generateAndUploadAvatar(handle: string): Promise<string | null> {
try {
// 1. Fetch the avatar from DiceBear
const dicebearUrl = `https://api.dicebear.com/9.x/bottts-neutral/svg?seed=${handle}`;
// 1. Fetch the avatar from DiceBear (PNG format for better compatibility)
const dicebearUrl = `https://api.dicebear.com/9.x/bottts-neutral/png?seed=${handle}`;
const response = await fetch(dicebearUrl);
if (!response.ok) {
@@ -29,13 +29,13 @@ export async function generateAndUploadAvatar(handle: string): Promise<string |
const bucket = process.env.STORAGE_BUCKET || 'synapsis';
// Sanitize handle for filename just in case
const safeHandle = handle.replace(/[^a-zA-Z0-9]/g, '');
const filename = `${uuidv4()}-${safeHandle}-avatar.svg`;
const filename = `${uuidv4()}-${safeHandle}-avatar.png`;
await s3.send(new PutObjectCommand({
Bucket: bucket,
Key: filename,
Body: buffer,
ContentType: 'image/svg+xml',
ContentType: 'image/png',
ACL: 'public-read',
}));
+1 -1
View File
@@ -200,7 +200,7 @@ export async function registerUser(
const fullHandle = `${handle.toLowerCase()}@${nodeDomain}`;
const avatarUrl = await generateAndUploadAvatarToUserStorage(
fullHandle,
storageEndpoint || null,
storageEndpoint || undefined,
storageRegion,
storageBucket,
storageAccessKey,