fix(security): remove MinIO hardcoded credentials & add presigned URL support

- Remove hardcoded minioadmin/minioadmin_secret fallback from docker-compose.yml,
  require MINIO_ACCESS_KEY/MINIO_SECRET_KEY env vars (fail-fast with :? syntax)
- Align docker-compose.yml env var names with .env.example (MINIO_ACCESS_KEY/SECRET_KEY)
- Update CI e2e workflow to use GitHub vars with non-default fallbacks
- Update .env.test to use non-default test credentials
- Add @aws-sdk/s3-request-presigner and getPresignedUploadUrl() method to
  MinioMediaStorageService for properly signed client-side uploads
- Remove hardcoded credentials from dev-environment docs

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-08 22:44:50 +07:00
parent 8a86cf42d4
commit 03231271ca
7 changed files with 50 additions and 9 deletions

View File

@@ -7,6 +7,7 @@ import {
HeadBucketCommand,
CreateBucketCommand,
} from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { Injectable, type OnModuleInit } from '@nestjs/common';
import { type LoggerService } from '@modules/shared/infrastructure/logger.service';
@@ -15,6 +16,7 @@ export const MEDIA_STORAGE_SERVICE = Symbol('MEDIA_STORAGE_SERVICE');
export interface IMediaStorageService {
upload(buffer: Buffer, originalName: string, mimeType: string, folder: string): Promise<string>;
delete(fileUrl: string): Promise<void>;
getPresignedUploadUrl(objectKey: string, mimeType: string, expiresInSeconds?: number): Promise<string>;
}
function requireEnv(key: string): string {
@@ -106,6 +108,15 @@ export class MinioMediaStorageService implements IMediaStorageService, OnModuleI
}
}
async getPresignedUploadUrl(objectKey: string, mimeType: string, expiresInSeconds = 300): Promise<string> {
const command = new PutObjectCommand({
Bucket: this.bucket,
Key: objectKey,
ContentType: mimeType,
});
return getSignedUrl(this.s3, command, { expiresIn: expiresInSeconds });
}
async delete(fileUrl: string): Promise<void> {
try {
const urlObj = new URL(fileUrl);