You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Supabase插入数据违反行级安全策略错误排查求助

问题:插入user_profiles表时触发行级安全策略错误

当尝试向user_profiles表插入新行时,出现错误:"New row violates row-level security policy for table"。该表存在指向auth.users.id的外键user_id。

我通过supabase.auth.onAuthStateChange钩子,期望在用户登录时自动插入新行。最初启用RLS(行级安全)但未配置任何策略,之后尝试添加仅允许认证用户插入行的模板策略,问题未解决;参考相关内容添加认证用户查询的模板策略后,仍报相同错误。

认证逻辑在Chrome浏览器扩展的后台脚本中实现,相关代码如下:

supabase.ts

import { createClient } from '@supabase/supabase-js'
import qs from 'qs'

const supaUrl = import.meta.env.VITE_SUPABASE_URL
const supaANONKey = import.meta.env.VITE_SUPABASE_ANON_KEY
export const supabase = createClient(supaUrl, supaANONKey, {
  global: {
    fetch: (...args) => fetch(...args),
  },
})

export const extensionSupabaseLogin = async () => {
  const redirectUri = chrome.identity.getRedirectURL('supabase-auth')
  const options = {
    provider: 'notion',
    redirect_to: redirectUri,
    ux_mode: 'redirect',
  }
  const url = `${supaUrl}/auth/v1/authorize?${qs.stringify(options)}`

  const originalTab = (await chrome.tabs.query({ active: true, currentWindow: true }))[0]
  const authenticationTab = await chrome.tabs.create({ url: 'about:blank' })
  chrome.tabs.onUpdated.addListener(function notionAuthHook(tabId, _changeInfo, tab) {
    if (tabId === authenticationTab.id && tab.url?.startsWith(redirectUri)) {
      const splitUrl = tab.url?.split('#')[1]
      // 解析失败时提示用户重新登录(错误情况)
      if (!splitUrl) {
        console.error('无法解析登录URL', tab.url)
        return
      }
      // 从URL中解析令牌
      const authResult = qs.parse(splitUrl)
      const refreshToken = authResult.refresh_token as string
      const accessToken = authResult.access_token as string

      // 无access_token时提示用户重新登录(错误情况)
      if (!refreshToken || !accessToken) {
        console.error('未返回access token或refresh token', authResult)
        return
      }

      ;(async () => {
        const { error } = await supabase.auth.setSession({
          access_token: accessToken,
          refresh_token: refreshToken,
        })
        if (error) console.error(error)
      })()

      chrome.tabs.onUpdated.removeListener(notionAuthHook)
      chrome.tabs.remove(tabId)
      if (originalTab?.id) {
        chrome.tabs.update(originalTab.id, { active: true })
      }
    }
  })
  // 引导用户进入登录流程
  if (authenticationTab.id) {
    await chrome.tabs.update(authenticationTab.id, { url: url })
  }
}

background.ts

import { Client } from '@notionhq/client'
import { extensionSupabaseLogin, supabase } from './supabase'

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === 'signIn') {
    extensionSupabaseLogin();
  } else if (request.type === 'GET_NOTION_PAGE') {
     const { accessToken, ...options } = request.options as GetPageNotionOptions
     debugger
     if (!notionClient) {
       setNotionClient(accessToken)
     }
     if (notionClient) {
       const response = await notionClient.pages.retrieve({ ...options })
       sendResponse({ type: 'SUCCESS', data: JSON.stringify(response) })
     }
  }
});

let notionClient: Client | null = null

const setNotionClient = (notionCode: string) => {
   notionClient = new Client({
      auth: notionCode,
   })
}

const storeNotionIdentity = async (notionIdentity: { accessToken: string; refreshToken?: string }): Promise<void> => {
  setNotionClient(notionIdentity.accessToken)
  await chrome.storage.local.set({
    notionIdentity,
  })
}

const storeNotionUser = async (user: User): Promise<void> => {
  await chrome.storage.local.set({
    user,
  })
}

const setupAuthListener = () => {
    supabase.auth.onAuthStateChange(async (event, session) => {
      if (event === 'SIGNED_IN' || event === 'USER_UPDATED') {
        // 用户刚登录或会话已更新
        console.log('用户已登录 :', session)
        if (session?.access_token && session?.refresh_token) {
          debugger
          await storeNotionIdentity({ accessToken: session.access_token, refreshToken: session.refresh_token })
        }
        if (session?.user) {
          await storeNotionUser({
            name: session.user.user_metadata?.name,
            fullName: session.user.user_metadata?.full_name,
            email: session.user?.email ?? session.user.user_metadata?.email,
            userId: session.user.id,
          })
        }
        if (typeof loginTabId === 'number') {
          chrome.tabs.sendMessage(loginTabId, `notion登录成功`)
        }
      } else if (event === 'SIGNED_OUT') {
        // 用户刚登出或账号已被删除
        console.log('用户已登出')
        loginTabId = null
        await chrome.storage.local.remove(['notionIdentity', 'user'])
      }
    })
  }
  
  setupAuthListener()

内容的提问来源于stack exchange,提问作者Matt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 11:54:53