feat: add data privacy settings screen and initialize backend service infrastructure

This commit is contained in:
2026-04-03 19:41:04 +02:00
parent 08483c7075
commit c13eb331be
11 changed files with 110 additions and 201 deletions

View File

@@ -15,10 +15,10 @@ const isStorageConfigured = () => Boolean(MINIO_ENDPOINT && MINIO_ACCESS_KEY &&
const getMinioPublicUrl = () =>
getTrimmedEnv('MINIO_PUBLIC_URL', `http://${MINIO_ENDPOINT}:${MINIO_PORT}`).replace(/\/$/, '');
const getClient = () => {
if (!isStorageConfigured()) {
throw new Error('Image storage is not configured.');
}
const getClient = () => {
if (!isStorageConfigured()) {
throw new Error('Image storage is not configured.');
}
return new Minio.Client({
endPoint: MINIO_ENDPOINT,
@@ -26,13 +26,15 @@ const getClient = () => {
useSSL: MINIO_USE_SSL,
accessKey: MINIO_ACCESS_KEY,
secretKey: MINIO_SECRET_KEY,
});
};
const ensureStorageBucket = async () => {
const client = getClient();
const exists = await client.bucketExists(MINIO_BUCKET);
if (!exists) {
});
};
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const ensureStorageBucket = async () => {
const client = getClient();
const exists = await client.bucketExists(MINIO_BUCKET);
if (!exists) {
await client.makeBucket(MINIO_BUCKET);
const policy = JSON.stringify({
Version: '2012-10-17',
@@ -46,13 +48,35 @@ const ensureStorageBucket = async () => {
],
});
await client.setBucketPolicy(MINIO_BUCKET, policy);
console.log(`MinIO bucket '${MINIO_BUCKET}' created with public read policy.`);
}
};
const uploadImage = async (base64Data, contentType = 'image/jpeg') => {
const client = getClient();
const rawExtension = contentType.split('/')[1] || 'jpg';
console.log(`MinIO bucket '${MINIO_BUCKET}' created with public read policy.`);
}
};
const ensureStorageBucketWithRetry = async (options = {}) => {
const attempts = Number(options.attempts || 5);
const delayMs = Number(options.delayMs || 2000);
let lastError;
for (let attempt = 1; attempt <= attempts; attempt += 1) {
try {
await ensureStorageBucket();
return;
} catch (error) {
lastError = error;
if (attempt === attempts) break;
console.warn(
`MinIO bucket setup attempt ${attempt}/${attempts} failed: ${error.message}. Retrying in ${delayMs}ms...`,
);
await sleep(delayMs);
}
}
throw lastError;
};
const uploadImage = async (base64Data, contentType = 'image/jpeg') => {
const client = getClient();
const rawExtension = contentType.split('/')[1] || 'jpg';
const extension = rawExtension === 'jpeg' ? 'jpg' : rawExtension;
const filename = `${Date.now()}-${crypto.randomBytes(8).toString('hex')}.${extension}`;
const buffer = Buffer.from(base64Data, 'base64');
@@ -65,8 +89,9 @@ const uploadImage = async (base64Data, contentType = 'image/jpeg') => {
return { url, filename };
};
module.exports = {
ensureStorageBucket,
uploadImage,
isStorageConfigured,
};
module.exports = {
ensureStorageBucket,
ensureStorageBucketWithRetry,
uploadImage,
isStorageConfigured,
};