/* |-------------------------------------------------------------------------- | Agência PSI — Edge Function: deactivate-notification-channel |-------------------------------------------------------------------------- | Desativa um canal de notificação (soft delete) usando service_role pra | bypassar RLS. Usado pelo chooser de WhatsApp quando o tenant quer trocar | de provedor mas o canal foi criado pelo SaaS admin (owner_id != tenant). | | Autoriza: apenas membros ativos do tenant dono do canal. |-------------------------------------------------------------------------- */ import { createClient } from 'https://esm.sh/@supabase/supabase-js@2' const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', 'Access-Control-Allow-Methods': 'POST, OPTIONS', } function json(body: unknown, status = 200) { return new Response(JSON.stringify(body), { status, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }) } Deno.serve(async (req: Request) => { if (req.method === 'OPTIONS') return new Response('ok', { headers: corsHeaders }) if (req.method !== 'POST') return json({ ok: false, error: 'method_not_allowed' }, 405) try { const body = await req.json().catch(() => null) as { channel_id?: string } | null const channelId = body?.channel_id if (!channelId) return json({ ok: false, error: 'channel_id ausente' }, 400) // Auth: valida user via JWT const authHeader = req.headers.get('Authorization') if (!authHeader) return json({ ok: false, error: 'unauthorized' }, 401) const supaAuth = createClient( Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_ANON_KEY')!, { global: { headers: { Authorization: authHeader } } } ) const { data: authData, error: authErr } = await supaAuth.auth.getUser() if (authErr || !authData?.user) return json({ ok: false, error: 'unauthorized' }, 401) const userId = authData.user.id // Service role pra bypass RLS const supaSvc = createClient( Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')! ) // Busca o canal const { data: channel, error: chErr } = await supaSvc .from('notification_channels') .select('id, tenant_id') .eq('id', channelId) .is('deleted_at', null) .maybeSingle() if (chErr || !channel) return json({ ok: false, error: 'channel_not_found' }, 404) // Autoriza: user deve ser saas_admin OU membro ativo do tenant dono do canal const { data: isAdmin } = await supaSvc.rpc('is_saas_admin') let authorized = !!isAdmin if (!authorized) { const { data: membership } = await supaSvc .from('tenant_members') .select('id') .eq('tenant_id', channel.tenant_id) .eq('user_id', userId) .eq('status', 'active') .maybeSingle() authorized = !!membership } if (!authorized) return json({ ok: false, error: 'forbidden' }, 403) // Desativa (soft-delete) const { error: updErr } = await supaSvc .from('notification_channels') .update({ is_active: false, deleted_at: new Date().toISOString() }) .eq('id', channelId) if (updErr) { console.error('[deactivate-notification-channel] update error:', updErr.message) return json({ ok: false, error: updErr.message }, 500) } return json({ ok: true, channel_id: channelId }) } catch (err) { console.error('[deactivate-notification-channel] fatal:', err) return json({ ok: false, error: String(err) }, 500) } })