mirror of
https://github.com/domfelipe/mika-agent-assist.git
synced 2026-08-07 09:16:46 +00:00
Changes
Co-authored-by: domfelipe <53182096+domfelipe@users.noreply.github.com>
This commit is contained in:
parent
6078ed674c
commit
97ee1930bb
2 changed files with 290 additions and 0 deletions
96
supabase/functions/test-integration/index.ts
Normal file
96
supabase/functions/test-integration/index.ts
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// Testa uma integração OAuth fazendo uma chamada leve ao provider.
|
||||
// Não consome refresh token. Atualiza status caso receba 401.
|
||||
import { createClient } from "npm:@supabase/supabase-js@2";
|
||||
import { corsHeaders } from "../_shared/cors.ts";
|
||||
import { type ProviderSlug, testProviderConnection } from "../_shared/oauth-providers.ts";
|
||||
|
||||
const SUPABASE_URL = Deno.env.get("SUPABASE_URL")!;
|
||||
const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!;
|
||||
|
||||
const admin = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
|
||||
|
||||
function json(body: unknown, status = 200) {
|
||||
return new Response(JSON.stringify(body), {
|
||||
status,
|
||||
headers: { ...corsHeaders, "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
Deno.serve(async (req) => {
|
||||
if (req.method === "OPTIONS") return new Response(null, { headers: corsHeaders });
|
||||
|
||||
const authHeader = req.headers.get("Authorization");
|
||||
if (!authHeader) return json({ error: "Não autenticado" }, 401);
|
||||
|
||||
const token = authHeader.replace("Bearer ", "");
|
||||
const { data: userData, error: userErr } = await admin.auth.getUser(token);
|
||||
if (userErr || !userData?.user) return json({ error: "Não autenticado" }, 401);
|
||||
const userId = userData.user.id;
|
||||
|
||||
let body: { integration_id?: string };
|
||||
try {
|
||||
body = await req.json();
|
||||
} catch {
|
||||
return json({ error: "JSON inválido" }, 400);
|
||||
}
|
||||
|
||||
const { integration_id } = body;
|
||||
if (!integration_id) return json({ error: "integration_id é obrigatório" }, 400);
|
||||
|
||||
// Busca integração + ownership + mcp slug
|
||||
const { data: integration, error: intErr } = await admin
|
||||
.from("user_integrations")
|
||||
.select(
|
||||
"id, user_id, status, access_token_vault_id, mcp_id, available_mcps!inner(slug, supports_refresh_token)",
|
||||
)
|
||||
.eq("id", integration_id)
|
||||
.maybeSingle();
|
||||
|
||||
if (intErr || !integration) return json({ error: "Integração não encontrada" }, 404);
|
||||
if (integration.user_id !== userId) return json({ error: "Acesso negado" }, 403);
|
||||
if (!integration.access_token_vault_id) return json({ error: "Token ausente" }, 400);
|
||||
|
||||
// @ts-expect-error nested
|
||||
const slug = integration.available_mcps.slug as ProviderSlug;
|
||||
// @ts-expect-error nested
|
||||
const supportsRefresh = integration.available_mcps.supports_refresh_token as boolean;
|
||||
|
||||
// Decrypt access token
|
||||
const { data: secretRows, error: secretErr } = await admin.rpc("vault_decrypt_secret", {
|
||||
secret_id: integration.access_token_vault_id,
|
||||
});
|
||||
if (secretErr || !secretRows?.[0]?.decrypted_secret) {
|
||||
return json({ error: "Falha ao recuperar token" }, 500);
|
||||
}
|
||||
const accessToken = secretRows[0].decrypted_secret as string;
|
||||
|
||||
try {
|
||||
const result = await testProviderConnection(slug, accessToken);
|
||||
if (result.ok) {
|
||||
// Garante status 'active' se estava em erro/expirado
|
||||
if (integration.status !== "active") {
|
||||
await admin
|
||||
.from("user_integrations")
|
||||
.update({ status: "active", error_message: null, updated_at: new Date().toISOString() })
|
||||
.eq("id", integration_id);
|
||||
}
|
||||
return json({ success: true, account_info: result.account ?? null });
|
||||
}
|
||||
if (result.status === 401) {
|
||||
const newStatus = supportsRefresh ? "expired" : "revoked";
|
||||
await admin
|
||||
.from("user_integrations")
|
||||
.update({
|
||||
status: newStatus,
|
||||
error_message: "Token inválido. Reconecte a integração.",
|
||||
updated_at: new Date().toISOString(),
|
||||
})
|
||||
.eq("id", integration_id);
|
||||
return json({ error: "Token inválido", status: newStatus }, 401);
|
||||
}
|
||||
return json({ error: `Provider retornou ${result.status}` }, 502);
|
||||
} catch (e) {
|
||||
console.error("test-integration error", e instanceof Error ? e.message : "unknown");
|
||||
return json({ error: "Falha ao testar conexão" }, 500);
|
||||
}
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue