W n8n route
This commit is contained in:
parent
2be19ea579
commit
3f56b98ae5
@ -20,24 +20,21 @@ interface MissionCreateInput {
|
|||||||
guardians?: Record<string, string>;
|
guardians?: Record<string, string>;
|
||||||
volunteers?: string[];
|
volunteers?: string[];
|
||||||
creatorId?: string;
|
creatorId?: string;
|
||||||
config?: {
|
|
||||||
N8N_API_KEY: string;
|
|
||||||
MISSION_API_URL: string;
|
|
||||||
};
|
|
||||||
logo?: {
|
logo?: {
|
||||||
data: string;
|
data: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
type?: string;
|
type?: string;
|
||||||
} | null;
|
} | null;
|
||||||
|
attachments?: Array<{
|
||||||
|
data: string;
|
||||||
|
name?: string;
|
||||||
|
type?: string;
|
||||||
|
}>;
|
||||||
leantimeProjectId?: string | null;
|
leantimeProjectId?: string | null;
|
||||||
outlineCollectionId?: string | null;
|
outlineCollectionId?: string | null;
|
||||||
rocketChatChannelId?: string | null;
|
rocketChatChannelId?: string | null;
|
||||||
gitRepositoryId?: string | null;
|
|
||||||
giteaRepositoryUrl?: string | null;
|
giteaRepositoryUrl?: string | null;
|
||||||
penpotProjectId?: string | null;
|
penpotProjectId?: string | null;
|
||||||
status?: string;
|
|
||||||
createdAt?: Date;
|
|
||||||
updatedAt?: Date;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MissionUserInput {
|
interface MissionUserInput {
|
||||||
@ -47,6 +44,7 @@ interface MissionUserInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface MissionResponse {
|
interface MissionResponse {
|
||||||
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
oddScope: string[];
|
oddScope: string[];
|
||||||
niveau: string;
|
niveau: string;
|
||||||
@ -64,20 +62,17 @@ interface MissionResponse {
|
|||||||
rocketChatChannelId: string | null;
|
rocketChatChannelId: string | null;
|
||||||
giteaRepositoryUrl: string | null;
|
giteaRepositoryUrl: string | null;
|
||||||
penpotProjectId: string | null;
|
penpotProjectId: string | null;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to check authentication
|
// Helper function to check authentication
|
||||||
async function checkAuth(request: Request) {
|
async function checkAuth(request: Request) {
|
||||||
const apiKey = request.headers.get('x-api-key');
|
|
||||||
if (apiKey === process.env.N8N_API_KEY) {
|
|
||||||
return { authorized: true, userId: 'system' };
|
|
||||||
}
|
|
||||||
|
|
||||||
const session = await getServerSession(authOptions);
|
const session = await getServerSession(authOptions);
|
||||||
if (!session?.user?.id) {
|
return {
|
||||||
return { authorized: false, userId: null };
|
authorized: !!session?.user,
|
||||||
}
|
userId: session?.user?.id
|
||||||
return { authorized: true, userId: session.user.id };
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET endpoint to list missions
|
// GET endpoint to list missions
|
||||||
@ -159,11 +154,10 @@ export async function POST(request: Request) {
|
|||||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const requestId = request.headers.get('x-request-id');
|
|
||||||
const body = await request.json() as MissionCreateInput;
|
const body = await request.json() as MissionCreateInput;
|
||||||
|
|
||||||
// Validate required fields
|
// Validate required fields
|
||||||
const requiredFields = ['name', 'niveau', 'intention', 'missionType', 'donneurDOrdre', 'projection'];
|
const requiredFields = ['name', 'oddScope'];
|
||||||
const missingFields = requiredFields.filter(field => !body[field as keyof MissionCreateInput]);
|
const missingFields = requiredFields.filter(field => !body[field as keyof MissionCreateInput]);
|
||||||
|
|
||||||
if (missingFields.length > 0) {
|
if (missingFields.length > 0) {
|
||||||
@ -179,7 +173,7 @@ export async function POST(request: Request) {
|
|||||||
// Get the creator ID from the appropriate source
|
// Get the creator ID from the appropriate source
|
||||||
const creatorId = isN8nRequest ? body.creatorId : userId;
|
const creatorId = isN8nRequest ? body.creatorId : userId;
|
||||||
|
|
||||||
// Verify creator exists for both n8n and non-n8n requests
|
// Verify creator exists
|
||||||
const creator = await prisma.user.findUnique({
|
const creator = await prisma.user.findUnique({
|
||||||
where: { id: creatorId }
|
where: { id: creatorId }
|
||||||
});
|
});
|
||||||
@ -217,24 +211,6 @@ export async function POST(request: Request) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for mission creation in progress
|
|
||||||
const missionInProgress = await prisma.mission.findFirst({
|
|
||||||
where: {
|
|
||||||
name: body.name,
|
|
||||||
createdAt: {
|
|
||||||
gte: new Date(Date.now() - 5 * 60 * 1000) // Within last 5 minutes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (missionInProgress) {
|
|
||||||
return NextResponse.json({
|
|
||||||
error: 'Mission creation already in progress',
|
|
||||||
details: 'Please wait a few minutes and try again',
|
|
||||||
code: 'MISSION_CREATION_IN_PROGRESS'
|
|
||||||
}, { status: 409 });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle n8n workflow
|
// Handle n8n workflow
|
||||||
if (!isN8nRequest) {
|
if (!isN8nRequest) {
|
||||||
const n8nService = new N8nService();
|
const n8nService = new N8nService();
|
||||||
@ -259,6 +235,7 @@ export async function POST(request: Request) {
|
|||||||
name: body.logo.name || 'logo.png',
|
name: body.logo.name || 'logo.png',
|
||||||
type: body.logo.type || 'image/png'
|
type: body.logo.type || 'image/png'
|
||||||
} : null,
|
} : null,
|
||||||
|
attachments: body.attachments || [],
|
||||||
config: {
|
config: {
|
||||||
N8N_API_KEY: process.env.N8N_API_KEY,
|
N8N_API_KEY: process.env.N8N_API_KEY,
|
||||||
MISSION_API_URL: process.env.NEXT_PUBLIC_API_URL || 'https://api.slm-lab.net/api'
|
MISSION_API_URL: process.env.NEXT_PUBLIC_API_URL || 'https://api.slm-lab.net/api'
|
||||||
@ -266,25 +243,6 @@ export async function POST(request: Request) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Log the data we're sending (without sensitive info)
|
|
||||||
console.log('Sending data to n8n workflow:', {
|
|
||||||
name: n8nData.name,
|
|
||||||
creatorId: n8nData.creatorId,
|
|
||||||
oddScope: n8nData.oddScope,
|
|
||||||
niveau: n8nData.niveau,
|
|
||||||
intention: n8nData.intention?.substring(0, 100) + '...',
|
|
||||||
missionType: n8nData.missionType,
|
|
||||||
donneurDOrdre: n8nData.donneurDOrdre,
|
|
||||||
projection: n8nData.projection,
|
|
||||||
services: n8nData.services,
|
|
||||||
participation: n8nData.participation,
|
|
||||||
profils: n8nData.profils,
|
|
||||||
hasGuardians: Object.keys(n8nData.guardians).length > 0,
|
|
||||||
volunteersCount: n8nData.volunteers.length,
|
|
||||||
hasConfig: true,
|
|
||||||
configKeys: Object.keys(n8nData.config)
|
|
||||||
});
|
|
||||||
|
|
||||||
const workflowResult = await n8nService.triggerMissionCreation(n8nData);
|
const workflowResult = await n8nService.triggerMissionCreation(n8nData);
|
||||||
|
|
||||||
if (!workflowResult.success) {
|
if (!workflowResult.success) {
|
||||||
@ -296,12 +254,10 @@ export async function POST(request: Request) {
|
|||||||
}, { status: 500 });
|
}, { status: 500 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the workflow result
|
|
||||||
const results = workflowResult.results || {};
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
success: true,
|
success: true,
|
||||||
status: 'success',
|
status: 'success',
|
||||||
message: 'Mission created successfully',
|
message: 'Mission creation initiated',
|
||||||
mission: {
|
mission: {
|
||||||
name: n8nData.name,
|
name: n8nData.name,
|
||||||
oddScope: n8nData.oddScope,
|
oddScope: n8nData.oddScope,
|
||||||
@ -313,65 +269,15 @@ export async function POST(request: Request) {
|
|||||||
services: n8nData.services,
|
services: n8nData.services,
|
||||||
profils: n8nData.profils,
|
profils: n8nData.profils,
|
||||||
participation: n8nData.participation,
|
participation: n8nData.participation,
|
||||||
creatorId: n8nData.creatorId,
|
creatorId: n8nData.creatorId
|
||||||
logo: n8nData.logo,
|
|
||||||
leantimeProjectId: results.leantimeProjectId,
|
|
||||||
outlineCollectionId: results.outlineCollectionId,
|
|
||||||
rocketChatChannelId: results.rocketChatChannelId,
|
|
||||||
giteaRepositoryUrl: results.giteaRepositoryUrl,
|
|
||||||
penpotProjectId: results.penpotProjectId
|
|
||||||
},
|
|
||||||
integrationStatus: {
|
|
||||||
gitRepo: !!results.giteaRepositoryUrl,
|
|
||||||
leantimeProject: !!results.leantimeProjectId,
|
|
||||||
docCollection: !!results.outlineCollectionId,
|
|
||||||
rocketChatChannel: !!results.rocketChatChannelId
|
|
||||||
},
|
|
||||||
resourceStatus: {
|
|
||||||
gitRepo: !!results.giteaRepositoryUrl,
|
|
||||||
leantimeProject: !!results.leantimeProjectId,
|
|
||||||
docCollection: !!results.outlineCollectionId,
|
|
||||||
rocketChatChannel: !!results.rocketChatChannelId
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error triggering n8n workflow:', error);
|
console.error('Error triggering n8n workflow:', error);
|
||||||
|
return NextResponse.json({
|
||||||
// Check if it's an n8n workflow error
|
error: 'Failed to initiate mission creation',
|
||||||
if (error instanceof Error && error.message.includes('HTTP error! status: 500')) {
|
details: error instanceof Error ? error.message : String(error)
|
||||||
// Try to parse the error message for more details
|
}, { status: 500 });
|
||||||
const errorMatch = error.message.match(/body: ({.*})/);
|
|
||||||
let errorDetails = 'The mission creation process encountered an error';
|
|
||||||
|
|
||||||
if (errorMatch) {
|
|
||||||
try {
|
|
||||||
const errorBody = JSON.parse(errorMatch[1]);
|
|
||||||
errorDetails = errorBody.message || errorDetails;
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to parse error body:', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
error: 'Mission creation workflow failed',
|
|
||||||
details: errorDetails,
|
|
||||||
code: 'WORKFLOW_ERROR',
|
|
||||||
originalError: error.message
|
|
||||||
},
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle other types of errors
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
error: 'Failed to create mission resources',
|
|
||||||
details: error instanceof Error ? error.message : 'The mission creation process failed. Please try again later.',
|
|
||||||
code: 'WORKFLOW_ERROR'
|
|
||||||
},
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,47 +342,32 @@ export async function POST(request: Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format response to match workflow output
|
|
||||||
const missionResponse: MissionResponse = {
|
|
||||||
name: mission.name,
|
|
||||||
oddScope: mission.oddScope,
|
|
||||||
niveau: mission.niveau,
|
|
||||||
intention: mission.intention,
|
|
||||||
missionType: mission.missionType,
|
|
||||||
donneurDOrdre: mission.donneurDOrdre,
|
|
||||||
projection: mission.projection,
|
|
||||||
services: mission.services,
|
|
||||||
profils: mission.profils,
|
|
||||||
participation: mission.participation || 'default',
|
|
||||||
creatorId: mission.creatorId,
|
|
||||||
logo: mission.logo,
|
|
||||||
leantimeProjectId: (mission as any).leantimeProjectId,
|
|
||||||
outlineCollectionId: (mission as any).outlineCollectionId,
|
|
||||||
rocketChatChannelId: (mission as any).rocketChatChannelId,
|
|
||||||
giteaRepositoryUrl: (mission as any).giteaRepositoryUrl,
|
|
||||||
penpotProjectId: (mission as any).penpotProjectId
|
|
||||||
};
|
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
success: true,
|
success: true,
|
||||||
status: 'success',
|
status: 'success',
|
||||||
message: 'Mission created successfully',
|
message: 'Mission created successfully',
|
||||||
mission: missionResponse,
|
mission: {
|
||||||
integrationStatus: {
|
id: (mission as any).id,
|
||||||
gitRepo: !!missionResponse.giteaRepositoryUrl,
|
name: (mission as any).name,
|
||||||
leantimeProject: !!missionResponse.leantimeProjectId,
|
oddScope: (mission as any).oddScope,
|
||||||
docCollection: !!missionResponse.outlineCollectionId,
|
niveau: (mission as any).niveau,
|
||||||
rocketChatChannel: !!missionResponse.rocketChatChannelId
|
intention: (mission as any).intention,
|
||||||
},
|
missionType: (mission as any).missionType,
|
||||||
resourceStatus: {
|
donneurDOrdre: (mission as any).donneurDOrdre,
|
||||||
gitRepo: false,
|
projection: (mission as any).projection,
|
||||||
leantimeProject: true,
|
services: (mission as any).services,
|
||||||
docCollection: true,
|
profils: (mission as any).profils,
|
||||||
rocketChatChannel: true
|
participation: (mission as any).participation,
|
||||||
},
|
creatorId: (mission as any).creatorId,
|
||||||
errors: [
|
logo: (mission as any).logo,
|
||||||
'Git repository creation failed: Unknown error'
|
leantimeProjectId: (mission as any).leantimeProjectId,
|
||||||
]
|
outlineCollectionId: (mission as any).outlineCollectionId,
|
||||||
|
rocketChatChannelId: (mission as any).rocketChatChannelId,
|
||||||
|
giteaRepositoryUrl: (mission as any).giteaRepositoryUrl,
|
||||||
|
penpotProjectId: (mission as any).penpotProjectId,
|
||||||
|
createdAt: (mission as any).createdAt,
|
||||||
|
updatedAt: (mission as any).updatedAt
|
||||||
|
} as MissionResponse
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating mission:', error);
|
console.error('Error creating mission:', error);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user