feat: stored under org/project path
This commit is contained in:
parent
e2cfd6e27f
commit
bdf2c80782
|
|
@ -4,7 +4,8 @@
|
|||
"description": "Nano Banana Image Generation Service - REST API for AI-powered image generation using Gemini Flash Image model",
|
||||
"main": "dist/server.js",
|
||||
"scripts": {
|
||||
"dev": "echo 'Logs will be saved to api-dev.log' && tsx --watch src/server.ts 2>&1 | tee api-dev.log",
|
||||
"infra:up": "cd ../.. && docker compose up -d postgres minio storage-init",
|
||||
"dev": "npm run infra:up && echo 'Logs will be saved to api-dev.log' && tsx --watch src/server.ts 2>&1 | tee api-dev.log",
|
||||
"start": "node dist/server.js",
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
import { Request, Response, NextFunction } from 'express';
|
||||
|
||||
/**
|
||||
* Middleware to ensure only project keys can access generation endpoints
|
||||
* Master keys are for admin purposes only
|
||||
*/
|
||||
export function requireProjectKey(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): void {
|
||||
// This middleware assumes validateApiKey has already run and attached req.apiKey
|
||||
if (!req.apiKey) {
|
||||
res.status(401).json({
|
||||
error: 'Authentication required',
|
||||
message: 'API key validation must be performed first',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Block master keys from generation endpoints
|
||||
if (req.apiKey.keyType === 'master') {
|
||||
res.status(403).json({
|
||||
error: 'Forbidden',
|
||||
message: 'Master keys cannot be used for image generation. Please use a project-specific API key.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure project key has required IDs
|
||||
if (!req.apiKey.projectId) {
|
||||
res.status(400).json({
|
||||
error: 'Invalid API key',
|
||||
message: 'Project key must be associated with a project',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[${new Date().toISOString()}] Project key validated for generation: ${req.apiKey.id}`);
|
||||
|
||||
next();
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from "../middleware/promptEnhancement";
|
||||
import { asyncHandler } from "../middleware/errorHandler";
|
||||
import { validateApiKey } from "../middleware/auth/validateApiKey";
|
||||
import { requireProjectKey } from "../middleware/auth/requireProjectKey";
|
||||
import { rateLimitByApiKey } from "../middleware/auth/rateLimiter";
|
||||
import { GenerateImageResponse } from "../types/api";
|
||||
// Create router
|
||||
|
|
@ -30,6 +31,7 @@ generateRouter.post(
|
|||
"/generate",
|
||||
// Authentication middleware
|
||||
validateApiKey,
|
||||
requireProjectKey,
|
||||
rateLimitByApiKey,
|
||||
|
||||
// File upload middleware
|
||||
|
|
@ -64,8 +66,12 @@ generateRouter.post(
|
|||
const { prompt, filename } = req.body;
|
||||
const files = (req.files as Express.Multer.File[]) || [];
|
||||
|
||||
// Extract org/project IDs from validated API key
|
||||
const orgId = req.apiKey?.organizationId || undefined;
|
||||
const projectId = req.apiKey?.projectId!; // Guaranteed by requireProjectKey middleware
|
||||
|
||||
console.log(
|
||||
`[${timestamp}] [${requestId}] Starting image generation process`,
|
||||
`[${timestamp}] [${requestId}] Starting image generation process for org:${orgId}, project:${projectId}`,
|
||||
);
|
||||
|
||||
try {
|
||||
|
|
@ -102,6 +108,8 @@ generateRouter.post(
|
|||
const result = await imageGenService.generateImage({
|
||||
prompt,
|
||||
filename,
|
||||
orgId,
|
||||
projectId,
|
||||
...(referenceImages && { referenceImages }),
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
} from "../middleware/promptEnhancement";
|
||||
import { asyncHandler } from "../middleware/errorHandler";
|
||||
import { validateApiKey } from "../middleware/auth/validateApiKey";
|
||||
import { requireProjectKey } from "../middleware/auth/requireProjectKey";
|
||||
import { rateLimitByApiKey } from "../middleware/auth/rateLimiter";
|
||||
import { GenerateImageResponse } from "../types/api";
|
||||
|
||||
|
|
@ -25,6 +26,7 @@ textToImageRouter.post(
|
|||
"/text-to-image",
|
||||
// Authentication middleware
|
||||
validateApiKey,
|
||||
requireProjectKey,
|
||||
rateLimitByApiKey,
|
||||
|
||||
// JSON validation middleware
|
||||
|
|
@ -54,8 +56,12 @@ textToImageRouter.post(
|
|||
const requestId = req.requestId;
|
||||
const { prompt, filename } = req.body;
|
||||
|
||||
// Extract org/project IDs from validated API key
|
||||
const orgId = req.apiKey?.organizationId || undefined;
|
||||
const projectId = req.apiKey?.projectId!; // Guaranteed by requireProjectKey middleware
|
||||
|
||||
console.log(
|
||||
`[${timestamp}] [${requestId}] Starting text-to-image generation process`,
|
||||
`[${timestamp}] [${requestId}] Starting text-to-image generation process for org:${orgId}, project:${projectId}`,
|
||||
);
|
||||
|
||||
try {
|
||||
|
|
@ -67,6 +73,8 @@ textToImageRouter.post(
|
|||
const result = await imageGenService.generateImage({
|
||||
prompt,
|
||||
filename,
|
||||
orgId,
|
||||
projectId,
|
||||
});
|
||||
|
||||
// Log the result
|
||||
|
|
|
|||
Loading…
Reference in New Issue