From 7e04fcbbb0b7fa5c43ea23f3b11a38a7ebfaad75 Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Thu, 25 Dec 2025 23:54:18 +0700 Subject: [PATCH] fix: storage structure --- apps/api-service/src/routes/upload.ts | 10 ++--- apps/api-service/src/routes/v1/generations.ts | 4 ++ .../src/services/core/GenerationService.ts | 43 ++++++++++++++++--- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/apps/api-service/src/routes/upload.ts b/apps/api-service/src/routes/upload.ts index 9efbe37..031e766 100644 --- a/apps/api-service/src/routes/upload.ts +++ b/apps/api-service/src/routes/upload.ts @@ -40,11 +40,11 @@ uploadRouter.post( } // Extract org/project slugs from validated API key - const orgId = req.apiKey?.organizationSlug || 'default'; - const projectId = req.apiKey?.projectSlug!; // Guaranteed by requireProjectKey middleware + const orgSlug = req.apiKey?.organizationSlug || process.env.DEFAULT_ORG_SLUG || 'default'; + const projectSlug = req.apiKey?.projectSlug || process.env.DEFAULT_PROJECT_SLUG || 'main'; // Guaranteed by requireProjectKey middleware console.log( - `[${timestamp}] [${requestId}] Starting file upload for org:${orgId}, project:${projectId}`, + `[${timestamp}] [${requestId}] Starting file upload for org:${orgSlug}, project:${projectSlug}`, ); const file = req.file; @@ -59,8 +59,8 @@ uploadRouter.post( ); const uploadResult = await storageService.uploadFile( - orgId, - projectId, + orgSlug, + projectSlug, 'uploads', file.originalname, file.buffer, diff --git a/apps/api-service/src/routes/v1/generations.ts b/apps/api-service/src/routes/v1/generations.ts index f7cd5d6..4f9fd0f 100644 --- a/apps/api-service/src/routes/v1/generations.ts +++ b/apps/api-service/src/routes/v1/generations.ts @@ -114,10 +114,14 @@ generationsRouter.post( const projectId = req.apiKey.projectId; const apiKeyId = req.apiKey.id; + const organizationSlug = req.apiKey.organizationSlug || process.env.DEFAULT_ORG_SLUG || 'default'; + const projectSlug = req.apiKey.projectSlug || process.env.DEFAULT_PROJECT_SLUG || 'main'; const generation = await service.create({ projectId, apiKeyId, + organizationSlug, + projectSlug, prompt, referenceImages, aspectRatio, diff --git a/apps/api-service/src/services/core/GenerationService.ts b/apps/api-service/src/services/core/GenerationService.ts index 2f6aa67..d01ec32 100644 --- a/apps/api-service/src/services/core/GenerationService.ts +++ b/apps/api-service/src/services/core/GenerationService.ts @@ -1,7 +1,7 @@ import { randomUUID } from 'crypto'; import { eq, desc, count, and, isNull, inArray } from 'drizzle-orm'; import { db } from '@/db'; -import { generations, flows, images } from '@banatie/database'; +import { generations, flows, images, projects, organizations } from '@banatie/database'; import type { Generation, NewGeneration, @@ -20,6 +20,8 @@ import type { ReferenceImage } from '@/types/api'; export interface CreateGenerationParams { projectId: string; apiKeyId: string; + organizationSlug: string; // For storage paths (orgSlug/projectSlug/category/file) + projectSlug: string; // For storage paths prompt: string; referenceImages?: string[] | undefined; // Aliases to resolve aspectRatio?: string | undefined; @@ -151,8 +153,8 @@ export class GenerationService { filename: `gen_${generation.id}`, referenceImages: referenceImageBuffers, aspectRatio: params.aspectRatio || GENERATION_LIMITS.DEFAULT_ASPECT_RATIO, - orgId: 'default', - projectId: params.projectId, + orgId: params.organizationSlug, // Use slug for storage path + projectId: params.projectSlug, // Use slug for storage path meta: params.meta || {}, }); @@ -377,6 +379,27 @@ export class GenerationService { } } + /** + * Get organization and project slugs for storage paths + */ + private async getSlugs(projectId: string): Promise<{ orgSlug: string; projectSlug: string }> { + const project = await db.query.projects.findFirst({ + where: eq(projects.id, projectId), + with: { + organization: true, + }, + }); + + if (!project) { + throw new Error('Project not found'); + } + + return { + orgSlug: project.organization.slug, + projectSlug: project.slug, + }; + } + private async updateStatus( id: string, status: 'pending' | 'processing' | 'success' | 'failed', @@ -491,14 +514,17 @@ export class GenerationService { // Update status to processing await this.updateStatus(id, 'processing'); + // Get slugs for storage paths + const { orgSlug, projectSlug } = await this.getSlugs(generation.projectId); + // Use EXACT same parameters as original (no overrides) const genResult = await this.imageGenService.generateImage({ prompt: generation.prompt, filename: `gen_${id}`, referenceImages: [], // TODO: Re-resolve referenced images if needed aspectRatio: generation.aspectRatio || GENERATION_LIMITS.DEFAULT_ASPECT_RATIO, - orgId: 'default', - projectId: generation.projectId, + orgId: orgSlug, + projectId: projectSlug, meta: generation.meta as Record || {}, }); @@ -605,14 +631,17 @@ export class GenerationService { const promptToUse = updates.prompt || generation.prompt; const aspectRatioToUse = updates.aspectRatio || generation.aspectRatio || GENERATION_LIMITS.DEFAULT_ASPECT_RATIO; + // Get slugs for storage paths + const { orgSlug, projectSlug } = await this.getSlugs(generation.projectId); + // Regenerate image const genResult = await this.imageGenService.generateImage({ prompt: promptToUse, filename: `gen_${id}`, referenceImages: [], aspectRatio: aspectRatioToUse, - orgId: 'default', - projectId: generation.projectId, + orgId: orgSlug, + projectId: projectSlug, meta: updates.meta || generation.meta || {}, });