Initial commit for Greenlens
This commit is contained in:
72
server/lib/storage.js
Normal file
72
server/lib/storage.js
Normal file
@@ -0,0 +1,72 @@
|
||||
const Minio = require('minio');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const getTrimmedEnv = (name, fallback = '') => String(process.env[name] ?? fallback).trim();
|
||||
|
||||
const MINIO_ENDPOINT = getTrimmedEnv('MINIO_ENDPOINT');
|
||||
const MINIO_PORT = Number(process.env.MINIO_PORT || 9000);
|
||||
const MINIO_USE_SSL = process.env.MINIO_USE_SSL === 'true';
|
||||
const MINIO_ACCESS_KEY = getTrimmedEnv('MINIO_ACCESS_KEY');
|
||||
const MINIO_SECRET_KEY = getTrimmedEnv('MINIO_SECRET_KEY');
|
||||
const MINIO_BUCKET = getTrimmedEnv('MINIO_BUCKET', 'plant-images') || 'plant-images';
|
||||
|
||||
const isStorageConfigured = () => Boolean(MINIO_ENDPOINT && MINIO_ACCESS_KEY && MINIO_SECRET_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.');
|
||||
}
|
||||
|
||||
return new Minio.Client({
|
||||
endPoint: MINIO_ENDPOINT,
|
||||
port: MINIO_PORT,
|
||||
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) {
|
||||
await client.makeBucket(MINIO_BUCKET);
|
||||
const policy = JSON.stringify({
|
||||
Version: '2012-10-17',
|
||||
Statement: [
|
||||
{
|
||||
Effect: 'Allow',
|
||||
Principal: { AWS: ['*'] },
|
||||
Action: ['s3:GetObject'],
|
||||
Resource: [`arn:aws:s3:::${MINIO_BUCKET}/*`],
|
||||
},
|
||||
],
|
||||
});
|
||||
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';
|
||||
const extension = rawExtension === 'jpeg' ? 'jpg' : rawExtension;
|
||||
const filename = `${Date.now()}-${crypto.randomBytes(8).toString('hex')}.${extension}`;
|
||||
const buffer = Buffer.from(base64Data, 'base64');
|
||||
|
||||
await client.putObject(MINIO_BUCKET, filename, buffer, buffer.length, {
|
||||
'Content-Type': contentType,
|
||||
});
|
||||
|
||||
const url = `${getMinioPublicUrl()}/${MINIO_BUCKET}/${filename}`;
|
||||
return { url, filename };
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
ensureStorageBucket,
|
||||
uploadImage,
|
||||
isStorageConfigured,
|
||||
};
|
||||
Reference in New Issue
Block a user