// ENVIRONMENTS require('dotenv').config(); // SERVICES const logger = require("../services/logger.services.js"); // CONSTANTS const { MINIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY } = process.env; const Minio = require("minio"); const minioClient = new Minio.Client({ endPoint: MINIO_ENDPOINT, port: 443, useSSL: true, accessKey: MINIO_ACCESS_KEY, secretKey: MINIO_SECRET_KEY, }); /** * Create a new bucket and set default public policy */ async function createBucket(bucketName) { return new Promise((resolve, reject) => { minioClient.makeBucket(bucketName, "", function (err) { if (err) return reject(err); logger.info(`Bucket "${bucketName}" created successfully`); const policy = { Version: "2012-10-17", Statement: [ { Effect: "Allow", Principal: { AWS: "*" }, Action: ["s3:GetObject"], Resource: [`arn:aws:s3:::${bucketName}/*`], }, ], }; minioClient.setBucketPolicy(bucketName, JSON.stringify(policy), (err) => { if (err) return reject(err); logger.info(`Public policy applied to bucket "${bucketName}"`); resolve(); }); }); }); } /** * Delete an existing bucket (must be empty) */ async function deleteBucket(bucketName) { return new Promise((resolve, reject) => { minioClient.removeBucket(bucketName, function (err) { if (err) return reject(err); logger.info(`Bucket "${bucketName}" deleted successfully`); resolve(); }); }); } /** * Rename a bucket (create new, copy objects, delete old) */ async function renameBucket(oldBucket, newBucket) { try { await createBucket(newBucket); const objects = []; const stream = minioClient.listObjects(oldBucket, "", true); await new Promise((resolve, reject) => { stream.on("data", obj => objects.push(obj)); stream.on("end", resolve); stream.on("error", reject); }); for (const obj of objects) { await new Promise((resolve, reject) => { minioClient.copyObject( newBucket, obj.name, `/${oldBucket}/${obj.name}`, function (err, etag) { if (err) return reject(err); logger.info(`Copied ${obj.name} to ${newBucket}`); resolve(etag); } ); }); } if (objects.length > 0) { await minioClient.removeObjects( oldBucket, objects.map(o => o.name) ); } await deleteBucket(oldBucket); logger.info(`Bucket renamed from "${oldBucket}" to "${newBucket}"`); } catch (err) { throw err; } } /** * Get all buckets */ async function getAllBuckets() { return new Promise((resolve, reject) => { minioClient.listBuckets((err, buckets) => { if (err) return reject(err); resolve(buckets); }); }); } /** * Set bucket policy (public / private) */ async function setBucketPolicy(bucketName, policyType) { let policy = ""; if (policyType === "public") { policy = { Version: "2012-10-17", Statement: [ { Effect: "Allow", Principal: { AWS: ["*"] }, Action: ["s3:GetObject"], Resource: [`arn:aws:s3:::${bucketName}/*`] } ] }; } else if (policyType === "private") { policy = { Version: "2012-10-17", Statement: [] }; } else { throw new Error("Invalid policy type, use 'public' or 'private'"); } await minioClient.setBucketPolicy(bucketName, JSON.stringify(policy)); } module.exports = { minioClient, createBucket, deleteBucket, renameBucket, getAllBuckets, setBucketPolicy };