From 7b6401cc6f4ef09e5ed93499ae50cc0e21bc71dc Mon Sep 17 00:00:00 2001 From: alma Date: Sat, 24 May 2025 10:23:40 +0200 Subject: [PATCH] W n8n attention --- app/api/missions/route.ts | 386 +++++++++----------------------------- 1 file changed, 86 insertions(+), 300 deletions(-) diff --git a/app/api/missions/route.ts b/app/api/missions/route.ts index 36189f59..ef6ad2f2 100644 --- a/app/api/missions/route.ts +++ b/app/api/missions/route.ts @@ -154,329 +154,115 @@ export async function POST(request: Request) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } - const body = await request.json() as MissionCreateInput; + const body = await request.json(); - // Add detailed logging - console.log('Mission API - Request body:', { - name: body.name, - hasServices: Array.isArray(body.services), - services: body.services, - hasGite: body.services?.includes('Gite'), - isN8nRequest: request.headers.get('x-api-key') === process.env.N8N_API_KEY - }); - - // Validate required fields - const requiredFields = ['name', 'oddScope']; - const missingFields = requiredFields.filter(field => !body[field as keyof MissionCreateInput]); - - if (missingFields.length > 0) { + // Simple validation + if (!body.name || !body.oddScope) { return NextResponse.json({ error: 'Missing required fields', - missingFields + missingFields: ['name', 'oddScope'].filter(field => !body[field]) }, { status: 400 }); } // Check if this is a request from n8n const isN8nRequest = request.headers.get('x-api-key') === process.env.N8N_API_KEY; - // Get the creator ID from the appropriate source - const creatorId = isN8nRequest ? body.creatorId : userId; - - // Verify creator exists - const creator = await prisma.user.findUnique({ - where: { id: creatorId } - }); - - if (!creator) { - return NextResponse.json({ - error: 'Invalid creator ID', - details: 'The specified creator does not exist', - code: 'INVALID_CREATOR' - }, { status: 400 }); - } - - // Check if mission with same name exists - const existingMission = await prisma.mission.findFirst({ - where: { name: body.name } - }); - - if (existingMission) { - // Update existing mission with new integration IDs - const updatedMission = await prisma.mission.update({ - where: { id: existingMission.id }, - data: { - leantimeProjectId: body.leantimeProjectId ? String(body.leantimeProjectId) : null, - outlineCollectionId: body.outlineCollectionId || null, - rocketChatChannelId: body.rocketChatChannelId || null, - giteaRepositoryUrl: body.giteaRepositoryUrl || null, - penpotProjectId: body.penpotProjectId || null - } as Prisma.MissionUpdateInput - }); - - return NextResponse.json({ - message: 'Mission updated successfully', - mission: updatedMission, - isUpdate: true - }); - } - - // Handle n8n workflow if (!isN8nRequest) { - const n8nService = new N8nService(); - - // Prepare the data for n8n - const n8nData = { - name: body.name, - oddScope: Array.isArray(body.oddScope) ? body.oddScope : [body.oddScope], - niveau: body.niveau || 'default', - intention: body.intention?.trim() || '', - missionType: body.missionType || 'default', - donneurDOrdre: body.donneurDOrdre || 'default', - projection: body.projection || 'default', - services: Array.isArray(body.services) ? body.services : [], - participation: body.participation || 'default', - profils: Array.isArray(body.profils) ? body.profils : [], - guardians: body.guardians || {}, - volunteers: Array.isArray(body.volunteers) ? body.volunteers : [], - creatorId: userId, - logo: body.logo ? { - data: body.logo.data, - name: body.logo.name || 'logo.png', - type: body.logo.type || 'image/png' - } : null, - attachments: body.attachments || [], - config: { - N8N_API_KEY: process.env.N8N_API_KEY, - MISSION_API_URL: process.env.NEXT_PUBLIC_API_URL || 'https://api.slm-lab.net/api' - } - }; - try { + const n8nService = new N8nService(); + + // Prepare data for n8n + const n8nData = { + ...body, + creatorId: userId, + config: { + N8N_API_KEY: process.env.N8N_API_KEY, + MISSION_API_URL: process.env.NEXT_PUBLIC_API_URL + } + }; + + // Trigger n8n workflow first const workflowResult = await n8nService.triggerMissionCreation(n8nData); if (!workflowResult.success) { - console.error('n8n workflow failed:', workflowResult.error); return NextResponse.json({ error: 'Failed to create mission resources', - details: workflowResult.error || 'The mission creation process failed', - code: 'WORKFLOW_ERROR' + details: workflowResult.error }, { status: 500 }); } - return NextResponse.json({ - success: true, - status: 'success', - message: 'Mission creation initiated', - mission: { - name: n8nData.name, - oddScope: n8nData.oddScope, - niveau: n8nData.niveau, - intention: n8nData.intention, - missionType: n8nData.missionType, - donneurDOrdre: n8nData.donneurDOrdre, - projection: n8nData.projection, - services: n8nData.services, - profils: n8nData.profils, - participation: n8nData.participation, - creatorId: n8nData.creatorId - } - }); - } catch (error) { - console.error('Error triggering n8n workflow:', error); + // Only create mission in database after n8n succeeds + try { + const missionData = { + name: body.name, + oddScope: body.oddScope, + niveau: body.niveau, + intention: body.intention, + missionType: body.missionType, + donneurDOrdre: body.donneurDOrdre, + projection: body.projection, + services: body.services, + profils: body.profils, + participation: body.participation, + creatorId: userId, + logo: body.logo + }; + + const mission = await prisma.mission.create({ + data: missionData + }); + + return NextResponse.json({ + success: true, + mission, + message: 'Mission created successfully with all integrations' + }); + } catch (dbError) { + console.error('Database error creating mission:', dbError); + return NextResponse.json({ + error: 'Failed to create mission in database', + details: dbError instanceof Error ? dbError.message : String(dbError) + }, { status: 500 }); + } + } catch (n8nError) { + console.error('Error with n8n service:', n8nError); return NextResponse.json({ - error: 'Failed to initiate mission creation', - details: error instanceof Error ? error.message : String(error) + error: 'Failed to create mission resources', + details: n8nError instanceof Error ? n8nError.message : String(n8nError) + }, { status: 500 }); + } + } else { + // Handle n8n callback - update mission with integration IDs + try { + const mission = await prisma.mission.update({ + where: { id: body.missionId }, + data: { + leantimeProjectId: body.leantimeProjectId ? String(body.leantimeProjectId) : null, + outlineCollectionId: body.outlineCollectionId || null, + rocketChatChannelId: body.rocketChatChannelId || null, + giteaRepositoryUrl: body.giteaRepositoryUrl || null, + penpotProjectId: body.penpotProjectId || null + } as Prisma.MissionUpdateInput + }); + + return NextResponse.json({ + success: true, + mission, + message: 'Mission updated with integration IDs' + }); + } catch (dbError) { + console.error('Database error updating mission:', dbError); + return NextResponse.json({ + error: 'Failed to update mission with integration IDs', + details: dbError instanceof Error ? dbError.message : String(dbError) }, { status: 500 }); } } - - // Create mission directly (n8n request) - try { - const mission = await prisma.mission.create({ - data: { - name: body.name, - oddScope: body.oddScope || ['default'], - niveau: body.niveau, - intention: body.intention, - missionType: body.missionType, - donneurDOrdre: body.donneurDOrdre, - projection: body.projection, - services: Array.isArray(body.services) ? body.services.filter(Boolean) : [], - profils: Array.isArray(body.profils) ? body.profils.filter(Boolean) : [], - participation: body.participation || 'default', - creatorId: creatorId, - logo: body.logo || null, - leantimeProjectId: body.leantimeProjectId ? String(body.leantimeProjectId) : null, - outlineCollectionId: body.outlineCollectionId || null, - rocketChatChannelId: body.rocketChatChannelId || null, - giteaRepositoryUrl: body.giteaRepositoryUrl || null, - penpotProjectId: body.penpotProjectId || null - } as Prisma.MissionUncheckedCreateInput - }); - - // Add guardians and volunteers - if (body.guardians || body.volunteers) { - const missionUsers: MissionUserInput[] = []; - - // Add guardians - if (body.guardians) { - Object.entries(body.guardians).forEach(([role, userId]) => { - if (userId) { - missionUsers.push({ - role, - userId: userId as string, - missionId: mission.id - }); - } - }); - } - - // Add volunteers - if (body.volunteers && Array.isArray(body.volunteers)) { - body.volunteers.forEach(userId => { - if (userId) { - missionUsers.push({ - role: 'volontaire', - userId, - missionId: mission.id - }); - } - }); - } - - if (missionUsers.length > 0) { - await prisma.missionUser.createMany({ - data: missionUsers - }); - } - } - - // Handle Git repository creation - if (mission.services.includes('Gite')) { - try { - // Sanitize the mission name similar to n8n workflow - const sanitizedName = mission.name.toLowerCase() - .split('') - .map(c => { - if (c >= 'a' && c <= 'z') return c; - if (c >= '0' && c <= '9') return c; - if (c === ' ' || c === '-') return c; - return ''; - }) - .join('') - .split(' ') - .filter(Boolean) - .join('-'); - - console.log('Creating Git repository with name:', sanitizedName); - - const giteaResponse = await fetch(`${process.env.GITEA_API_URL}/user/repos`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `token ${process.env.GITEA_API_TOKEN}` - }, - body: JSON.stringify({ - name: sanitizedName, - private: true, - auto_init: true, - avatar_url: mission.logo || null - }) - }); - - if (!giteaResponse.ok) { - const errorData = await giteaResponse.json(); - console.error('Git repository creation failed:', { - status: giteaResponse.status, - statusText: giteaResponse.statusText, - error: errorData, - requestBody: { - name: sanitizedName, - private: true, - auto_init: true - } - }); - throw new Error(`Git repository creation failed: ${errorData.message || giteaResponse.statusText}`); - } - - const giteaData = await giteaResponse.json(); - console.log('Git repository created successfully:', giteaData.html_url); - - // Update the mission with the Git repository URL using the correct Prisma field - await prisma.mission.update({ - where: { id: mission.id }, - data: { - giteaRepositoryUrl: giteaData.html_url - } as Prisma.MissionUpdateInput - }); - - } catch (error) { - console.error('Error creating Git repository:', error); - if (error instanceof Error) { - throw new Error(`Failed to create Git repository: ${error.message}`); - } - throw new Error('Failed to create Git repository: Unknown error'); - } - } - - return NextResponse.json({ - success: true, - status: 'success', - message: 'Mission created successfully', - mission: { - id: (mission as any).id, - name: (mission as any).name, - oddScope: (mission as any).oddScope, - niveau: (mission as any).niveau, - intention: (mission as any).intention, - missionType: (mission as any).missionType, - donneurDOrdre: (mission as any).donneurDOrdre, - projection: (mission as any).projection, - services: (mission as any).services, - profils: (mission as any).profils, - participation: (mission as any).participation, - creatorId: (mission as any).creatorId, - logo: (mission as any).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, - createdAt: (mission as any).createdAt, - updatedAt: (mission as any).updatedAt - } as MissionResponse - }); - } catch (error) { - console.error('Error creating mission:', error); - if (error instanceof Prisma.PrismaClientKnownRequestError) { - if (error.code === 'P2003') { - return NextResponse.json({ - success: false, - status: 'error', - error: 'Invalid reference', - message: 'One or more referenced users do not exist', - code: 'INVALID_REFERENCE' - }, { status: 400 }); - } - } - return NextResponse.json( - { - success: false, - status: 'error', - error: 'Failed to create mission', - message: error instanceof Error ? error.message : String(error) - }, - { status: 500 } - ); - } } catch (error) { - console.error('Error creating mission:', error); - return NextResponse.json( - { - error: 'Failed to create mission', - details: error instanceof Error ? error.message : String(error) - }, - { status: 500 } - ); + console.error('Error in mission creation:', error); + return NextResponse.json({ + error: 'Failed to create mission', + details: error instanceof Error ? error.message : String(error) + }, { status: 500 }); } } \ No newline at end of file