missions s3

This commit is contained in:
alma 2025-05-06 12:07:27 +02:00
parent 2be6e130e9
commit f5d719ecc1
6 changed files with 64 additions and 21 deletions

View File

@ -2,6 +2,7 @@ import { NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from "@/app/api/auth/options";
import { prisma } from '@/lib/prisma';
import { getPublicUrl, S3_CONFIG } from '@/lib/s3';
// Helper function to check authentication
async function checkAuth(request: Request) {
@ -60,7 +61,13 @@ export async function GET(request: Request, props: { params: Promise<{ missionId
}
});
return NextResponse.json(attachments);
// Add public URLs to attachments
const attachmentsWithUrls = attachments.map(attachment => ({
...attachment,
publicUrl: getPublicUrl(attachment.filePath, S3_CONFIG.missionsBucket)
}));
return NextResponse.json(attachmentsWithUrls);
} catch (error) {
console.error('Error fetching mission attachments:', error);
return NextResponse.json({

View File

@ -3,7 +3,7 @@ import { getServerSession } from 'next-auth';
import { authOptions } from "@/app/api/auth/options";
import { prisma } from '@/lib/prisma';
import { deleteMissionLogo } from '@/lib/mission-uploads';
import { getPublicUrl } from '@/lib/s3';
import { getPublicUrl, S3_CONFIG } from '@/lib/s3';
// Helper function to check authentication
async function checkAuth(request: Request) {
@ -82,10 +82,10 @@ export async function GET(request: Request, props: { params: Promise<{ missionId
// Add public URLs to mission logo and attachments
const missionWithUrls = {
...mission,
logoUrl: mission.logo ? getPublicUrl(mission.logo) : null,
logoUrl: mission.logo ? getPublicUrl(mission.logo, S3_CONFIG.missionsBucket) : null,
attachments: mission.attachments.map((attachment: { id: string; filename: string; filePath: string; fileType: string; fileSize: number; createdAt: Date }) => ({
...attachment,
publicUrl: getPublicUrl(attachment.filePath)
publicUrl: getPublicUrl(attachment.filePath, S3_CONFIG.missionsBucket)
}))
};

View File

@ -3,6 +3,7 @@ import { getServerSession } from 'next-auth';
import { authOptions } from "@/app/api/auth/options";
import { prisma } from '@/lib/prisma';
import { getPublicUrl } from '@/lib/s3';
import { S3_CONFIG } from '@/lib/s3';
// Helper function to check authentication
async function checkAuth(request: Request) {
@ -86,7 +87,7 @@ export async function GET(request: Request) {
// Transform logo paths to public URLs
const missionsWithPublicUrls = missions.map(mission => ({
...mission,
logo: mission.logo ? getPublicUrl(mission.logo) : null
logo: mission.logo ? getPublicUrl(mission.logo, S3_CONFIG.missionsBucket) : null
}));
return NextResponse.json({

View File

@ -9,7 +9,7 @@ import {
generateMissionLogoUploadUrl,
generateMissionAttachmentUploadUrl
} from '@/lib/mission-uploads';
import { getPublicUrl } from '@/lib/s3';
import { getPublicUrl, S3_CONFIG } from '@/lib/s3';
// Helper function to check authentication
async function checkAuth(request: Request) {
@ -148,7 +148,7 @@ export async function POST(request: Request) {
console.log('Logo uploaded successfully to path:', filePath);
// Generate public URL
const publicUrl = getPublicUrl(filePath);
const publicUrl = getPublicUrl(filePath, S3_CONFIG.missionsBucket);
console.log('Public URL for logo:', publicUrl);
// Update mission record with logo path
@ -184,7 +184,7 @@ export async function POST(request: Request) {
console.log('Attachment uploaded successfully to path:', filePath);
// Generate public URL
const publicUrl = getPublicUrl(filePath);
const publicUrl = getPublicUrl(filePath, S3_CONFIG.missionsBucket);
console.log('Public URL for attachment:', publicUrl);
// Create attachment record in database

View File

@ -1,5 +1,6 @@
import { s3Client, putObject, generatePresignedUrl, S3_CONFIG, deleteObject } from '@/lib/s3';
import { PutObjectCommand } from '@aws-sdk/client-s3';
import { PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
/**
* Utilities for mission-related file uploads using Minio
@ -39,18 +40,18 @@ export async function uploadMissionLogo(
const buffer = Buffer.from(arrayBuffer);
console.log('Buffer created, size:', buffer.length);
// Upload to Minio
console.log('Creating S3 command with bucket:', S3_CONFIG.bucket);
// Upload to Minio using the missions bucket
console.log('Creating S3 command with bucket:', S3_CONFIG.missionsBucket);
console.log('S3 config:', {
endpoint: S3_CONFIG.endpoint || 'MISSING!',
region: S3_CONFIG.region || 'MISSING!',
bucket: S3_CONFIG.bucket || 'MISSING!',
bucket: S3_CONFIG.missionsBucket || 'MISSING!',
hasAccessKey: !!S3_CONFIG.accessKey || 'MISSING!',
hasSecretKey: !!S3_CONFIG.secretKey || 'MISSING!'
});
const command = new PutObjectCommand({
Bucket: S3_CONFIG.bucket,
Bucket: S3_CONFIG.missionsBucket,
Key: filePath,
Body: buffer,
ContentType: file.type,
@ -92,9 +93,9 @@ export async function uploadMissionAttachment(
const arrayBuffer = await file.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
// Upload to Minio
// Upload to Minio using missions bucket
const command = new PutObjectCommand({
Bucket: S3_CONFIG.bucket,
Bucket: S3_CONFIG.missionsBucket,
Key: filePath,
Body: buffer,
ContentType: file.type,
@ -114,6 +115,21 @@ export async function uploadMissionAttachment(
}
}
// Generate presigned URL for missions bucket
async function generateMissionPresignedUrl(key: string, expiresIn = 3600): Promise<string> {
try {
const command = new PutObjectCommand({
Bucket: S3_CONFIG.missionsBucket,
Key: key
});
return await getSignedUrl(s3Client, command, { expiresIn });
} catch (error) {
console.error('Error generating presigned URL for missions bucket:', error);
throw error;
}
}
// Generate presigned URL for direct browser upload of mission logo
export async function generateMissionLogoUploadUrl(
userId: string,
@ -126,7 +142,7 @@ export async function generateMissionLogoUploadUrl(
}> {
try {
const filePath = getMissionLogoPath(userId, missionId, fileExtension);
const uploadUrl = await generatePresignedUrl(filePath, expiresIn);
const uploadUrl = await generateMissionPresignedUrl(filePath, expiresIn);
return { uploadUrl, filePath };
} catch (error) {
@ -147,7 +163,7 @@ export async function generateMissionAttachmentUploadUrl(
}> {
try {
const filePath = getMissionAttachmentPath(userId, missionId, filename);
const uploadUrl = await generatePresignedUrl(filePath, expiresIn);
const uploadUrl = await generateMissionPresignedUrl(filePath, expiresIn);
return { uploadUrl, filePath };
} catch (error) {
@ -156,10 +172,26 @@ export async function generateMissionAttachmentUploadUrl(
}
}
// Delete object from missions bucket
async function deleteMissionObject(key: string): Promise<boolean> {
try {
const command = new DeleteObjectCommand({
Bucket: S3_CONFIG.missionsBucket,
Key: key
});
await s3Client.send(command);
return true;
} catch (error) {
console.error('Error deleting mission object:', error);
throw error;
}
}
// Delete mission attachment from Minio
export async function deleteMissionAttachment(filePath: string): Promise<boolean> {
try {
await deleteObject(filePath);
await deleteMissionObject(filePath);
return true;
} catch (error) {
console.error('Error deleting mission attachment:', error);
@ -170,7 +202,7 @@ export async function deleteMissionAttachment(filePath: string): Promise<boolean
// Delete mission logo from Minio
export async function deleteMissionLogo(filePath: string): Promise<boolean> {
try {
await deleteObject(filePath);
await deleteMissionObject(filePath);
return true;
} catch (error) {
console.error('Error deleting mission logo:', error);

View File

@ -20,6 +20,7 @@ export const S3_CONFIG = {
endpoint: process.env.MINIO_S3_UPLOAD_BUCKET_URL,
region: process.env.MINIO_AWS_REGION,
bucket: process.env.MINIO_AWS_S3_UPLOAD_BUCKET_NAME,
missionsBucket: process.env.MINIO_MISSIONS_BUCKET || 'missions',
accessKey: process.env.MINIO_ACCESS_KEY || process.env.AWS_ACCESS_KEY_ID,
secretKey: process.env.MINIO_SECRET_KEY || process.env.AWS_SECRET_ACCESS_KEY,
}
@ -247,7 +248,7 @@ export async function generatePresignedUrl(key: string, expiresIn = 3600) {
}
// Generate a public URL for a file stored in Minio/S3
export function getPublicUrl(filePath: string): string {
export function getPublicUrl(filePath: string, bucketName?: string): string {
if (!filePath) return '';
if (filePath.startsWith('http')) return filePath; // Already a full URL
@ -269,9 +270,11 @@ export function getPublicUrl(filePath: string): string {
}
}
// Determine which bucket to use
const bucket = bucketName || S3_CONFIG.bucket;
// Construct the full URL using the standard approach
const endpoint = S3_CONFIG.endpoint?.replace(/\/$/, ''); // Remove trailing slash if present
const bucket = S3_CONFIG.bucket;
console.log('S3 Config for URL generation:', {
endpoint,