Refactor: Move n8n workflow creation to backend
The frontend now calls a backend endpoint to create n8n workflows, addressing CORS issues. The backend handles the n8n API request, updates Supabase, and returns the result to the frontend.
This commit is contained in:
parent
71d2ef79c0
commit
8ec8b4a5c6
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import Layout from '@/components/layout/Layout';
|
import Layout from '@/components/layout/Layout';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
@ -106,7 +107,7 @@ const GruposWhatsApp = () => {
|
|||||||
if (errorMsg.includes('Status')) {
|
if (errorMsg.includes('Status')) {
|
||||||
const statusMatch = errorMsg.match(/Status (\d+)/);
|
const statusMatch = errorMsg.match(/Status (\d+)/);
|
||||||
if (statusMatch && statusMatch[1]) {
|
if (statusMatch && statusMatch[1]) {
|
||||||
setDebugInfo(`Código de status HTTP da API n8n: ${statusMatch[1]}`);
|
setDebugInfo(`Código de status HTTP da API: ${statusMatch[1]}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export async function cadastrarGrupoWhatsApp(): Promise<WhatsAppGroup | null> {
|
|||||||
const workflowResponse = await createWorkflowInN8n(userEmail);
|
const workflowResponse = await createWorkflowInN8n(userEmail);
|
||||||
|
|
||||||
if (workflowResponse && workflowResponse.id) {
|
if (workflowResponse && workflowResponse.id) {
|
||||||
// Atualizar o objeto com o workflow_id
|
// Update the group with workflow_id
|
||||||
await updateWorkflowId(group.id, workflowResponse.id);
|
await updateWorkflowId(group.id, workflowResponse.id);
|
||||||
group.workflow_id = workflowResponse.id;
|
group.workflow_id = workflowResponse.id;
|
||||||
console.log('Workflow criado com sucesso no n8n:', workflowResponse.id);
|
console.log('Workflow criado com sucesso no n8n:', workflowResponse.id);
|
||||||
@ -41,14 +41,14 @@ export async function cadastrarGrupoWhatsApp(): Promise<WhatsAppGroup | null> {
|
|||||||
}
|
}
|
||||||
} catch (n8nError) {
|
} catch (n8nError) {
|
||||||
console.error('Erro ao criar workflow no n8n:', n8nError);
|
console.error('Erro ao criar workflow no n8n:', n8nError);
|
||||||
// Não impede a criação do grupo, apenas não adiciona o workflow_id
|
// Don't prevent group creation, just continue without workflow_id
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always return the group, even if workflow creation fails
|
// Always return the group, even if workflow creation fails
|
||||||
return group;
|
return group;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erro ao cadastrar grupo do WhatsApp:', error);
|
console.error('Erro ao cadastrar grupo do WhatsApp:', error);
|
||||||
throw error; // Propaga o erro para ser tratado no componente
|
throw error; // Propagate error to be handled in the component
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
|
|
||||||
// Service dedicated to n8n workflow operations
|
// Service dedicated to n8n workflow operations
|
||||||
import { toast } from "@/hooks/use-toast";
|
import { toast } from "@/hooks/use-toast";
|
||||||
|
import { supabase } from "@/integrations/supabase/client";
|
||||||
const N8N_API_URL = 'https://n8n.innova1001.com.br/api/v1/workflows';
|
|
||||||
const N8N_API_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2YmM4MjQxOS0zZTk1LTRiYmMtODMwMy0xODAzZjk4YmQ4YjciLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwiaWF0IjoxNzQ3NzM0NzYyLCJleHAiOjE3NTAzMDIwMDB9.Evr_o42xLJPq1c2p5SUWo00IY85WXp8s_nqSy64V-is';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a workflow in the n8n system for a specific user
|
* Creates a workflow in the n8n system for a specific user
|
||||||
@ -12,67 +9,55 @@ const N8N_API_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2YmM4MjQxOS
|
|||||||
*/
|
*/
|
||||||
export async function createWorkflowInN8n(email: string): Promise<{ id: string } | null> {
|
export async function createWorkflowInN8n(email: string): Promise<{ id: string } | null> {
|
||||||
try {
|
try {
|
||||||
console.log(`Criando workflow no n8n para o email: ${email}`);
|
console.log(`Solicitando criação de workflow para o email: ${email}`);
|
||||||
|
|
||||||
// Nome do workflow formatado corretamente
|
// Find or create WhatsApp group for the user to get the group ID
|
||||||
const workflowName = `Workflow Home Finance - ${email}`;
|
const { data: grupos, error: gruposError } = await supabase
|
||||||
console.log(`Nome do workflow: ${workflowName}`);
|
.from('grupos_whatsapp')
|
||||||
|
.select('*')
|
||||||
|
.eq('login', email.trim().toLowerCase())
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
// Testar primeiro com uma requisição OPTIONS para verificar CORS
|
if (gruposError) {
|
||||||
console.log("Enviando requisição OPTIONS para verificar CORS...");
|
console.error("Erro ao buscar grupo do WhatsApp:", gruposError);
|
||||||
|
throw new Error("Não foi possível encontrar o grupo do WhatsApp associado ao usuário");
|
||||||
try {
|
|
||||||
const optionsResponse = await fetch(N8N_API_URL, {
|
|
||||||
method: 'OPTIONS',
|
|
||||||
headers: {
|
|
||||||
'Access-Control-Request-Method': 'POST',
|
|
||||||
'Access-Control-Request-Headers': 'Content-Type, X-N8N-API-KEY, Origin',
|
|
||||||
'Origin': window.location.origin
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("Resposta OPTIONS:", {
|
|
||||||
status: optionsResponse.status,
|
|
||||||
ok: optionsResponse.ok,
|
|
||||||
headers: Array.from(optionsResponse.headers.entries()),
|
|
||||||
statusText: optionsResponse.statusText
|
|
||||||
});
|
|
||||||
} catch (corsError) {
|
|
||||||
console.error("Erro no teste de CORS:", corsError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Agora fazer a requisição real
|
if (!grupos || grupos.length === 0) {
|
||||||
console.log("Enviando requisição POST para criar workflow...");
|
console.error("Nenhum grupo encontrado para o usuário");
|
||||||
|
throw new Error("Nenhum grupo do WhatsApp encontrado para o usuário");
|
||||||
|
}
|
||||||
|
|
||||||
const response = await fetch(N8N_API_URL, {
|
const grupo = grupos[0];
|
||||||
|
|
||||||
|
// If the group already has a workflow ID, return it
|
||||||
|
if (grupo.workflow_id) {
|
||||||
|
console.log(`Grupo já possui workflow ID: ${grupo.workflow_id}`);
|
||||||
|
return { id: grupo.workflow_id };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call our edge function to create the workflow
|
||||||
|
const response = await fetch(`${supabase.supabaseUrl}/functions/v1/create-n8n-workflow`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'X-N8N-API-KEY': N8N_API_KEY,
|
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Origin': window.location.origin
|
'Authorization': `Bearer ${supabase.auth.session()?.access_token || ''}`
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
name: workflowName,
|
email: email,
|
||||||
nodes: [],
|
grupoId: grupo.id
|
||||||
connections: {},
|
|
||||||
settings: {}
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
// Log detalhado do status da resposta
|
// Log detailed response status
|
||||||
console.log("Status da resposta n8n:", {
|
console.log(`Status da resposta da Edge Function: ${response.status}`);
|
||||||
status: response.status,
|
|
||||||
statusText: response.statusText,
|
|
||||||
ok: response.ok,
|
|
||||||
headers: Array.from(response.headers.entries())
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
let errorDetails = '';
|
let errorDetails = '';
|
||||||
try {
|
try {
|
||||||
const errorText = await response.text();
|
const errorBody = await response.json();
|
||||||
errorDetails = errorText;
|
errorDetails = JSON.stringify(errorBody);
|
||||||
console.error(`Erro ao criar workflow: Status ${response.status}`, errorText);
|
console.error(`Erro ao criar workflow através da Edge Function: Status ${response.status}`, errorBody);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Não foi possível ler o corpo da resposta de erro: ${e}`);
|
console.error(`Não foi possível ler o corpo da resposta de erro: ${e}`);
|
||||||
}
|
}
|
||||||
@ -82,7 +67,7 @@ export async function createWorkflowInN8n(email: string): Promise<{ id: string }
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
console.log('Resposta da criação de workflow:', data);
|
console.log('Resposta da criação de workflow:', data);
|
||||||
|
|
||||||
return data;
|
return { id: data.workflow_id };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erro na requisição de criação de workflow:', error);
|
console.error('Erro na requisição de criação de workflow:', error);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
120
supabase/functions/create-n8n-workflow/index.ts
Normal file
120
supabase/functions/create-n8n-workflow/index.ts
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
|
||||||
|
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
|
||||||
|
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
|
||||||
|
|
||||||
|
const N8N_API_URL = 'https://n8n.innova1001.com.br/api/v1/workflows';
|
||||||
|
const N8N_API_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2YmM4MjQxOS0zZTk1LTRiYmMtODMwMy0xODAzZjk4YmQ4YjciLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwiaWF0IjoxNzQ3NzM0NzYyLCJleHAiOjE3NTAzMDIwMDB9.Evr_o42xLJPq1c2p5SUWo00IY85WXp8s_nqSy64V-is';
|
||||||
|
|
||||||
|
serve(async (req) => {
|
||||||
|
// CORS headers
|
||||||
|
const headers = {
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle preflight requests
|
||||||
|
if (req.method === 'OPTIONS') {
|
||||||
|
return new Response(null, { headers, status: 204 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Parse the request body
|
||||||
|
const requestData = await req.json();
|
||||||
|
const { email, grupoId } = requestData;
|
||||||
|
|
||||||
|
if (!email) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({ error: 'Email é obrigatório' }),
|
||||||
|
{ status: 400, headers }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!grupoId) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({ error: 'ID do grupo é obrigatório' }),
|
||||||
|
{ status: 400, headers }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Creating workflow for email: ${email}, group ID: ${grupoId}`);
|
||||||
|
|
||||||
|
// Create Supabase client
|
||||||
|
const supabaseUrl = Deno.env.get('SUPABASE_URL') ?? '';
|
||||||
|
const supabaseAnonKey = Deno.env.get('SUPABASE_ANON_KEY') ?? '';
|
||||||
|
const supabase = createClient(supabaseUrl, supabaseAnonKey);
|
||||||
|
|
||||||
|
// Create workflow in n8n
|
||||||
|
const n8nResponse = await fetch(N8N_API_URL, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-N8N-API-KEY': N8N_API_KEY,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
name: `Workflow Home Finance - ${email}`,
|
||||||
|
nodes: [],
|
||||||
|
connections: {},
|
||||||
|
settings: {}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`N8N API response status: ${n8nResponse.status}`);
|
||||||
|
|
||||||
|
if (!n8nResponse.ok) {
|
||||||
|
const errorText = await n8nResponse.text();
|
||||||
|
console.error(`N8N API error: ${errorText}`);
|
||||||
|
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
error: 'Erro ao criar workflow no n8n',
|
||||||
|
details: errorText,
|
||||||
|
status: n8nResponse.status
|
||||||
|
}),
|
||||||
|
{ status: 500, headers }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const workflowData = await n8nResponse.json();
|
||||||
|
console.log(`Workflow created successfully with ID: ${workflowData.id}`);
|
||||||
|
|
||||||
|
// Update the workflow_id in grupos_whatsapp table
|
||||||
|
const { data: updateData, error: updateError } = await supabase
|
||||||
|
.from('grupos_whatsapp')
|
||||||
|
.update({ workflow_id: workflowData.id })
|
||||||
|
.eq('id', grupoId)
|
||||||
|
.select();
|
||||||
|
|
||||||
|
if (updateError) {
|
||||||
|
console.error(`Error updating grupo_whatsapp: ${JSON.stringify(updateError)}`);
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
error: 'Erro ao atualizar o grupo com o workflow ID',
|
||||||
|
details: updateError
|
||||||
|
}),
|
||||||
|
{ status: 500, headers }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Group ${grupoId} updated with workflow ID ${workflowData.id}`);
|
||||||
|
|
||||||
|
// Return success response
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
workflow_id: workflowData.id,
|
||||||
|
message: 'Workflow criado e associado ao grupo com sucesso'
|
||||||
|
}),
|
||||||
|
{ headers }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Unexpected error: ${error.message}`);
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
error: 'Erro interno do servidor',
|
||||||
|
details: error.message
|
||||||
|
}),
|
||||||
|
{ status: 500, headers }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user