即使通过 INSERT 在 postgres 控制台中工作,由于 RLS Supabase 插入失败
Supabase insert fails due to RLS even through INSERT works in postgres console
我正在 supabase 中实现一个身份验证框架,它支持具有各种权限的多个角色,因此为不同的场景创建多个策略。
我的所有策略都包含一组集成测试以确保连续性。
我面临的一个特殊问题是来自 supabase JS API 的 INSERT 语句由于行级验证而失败,即使通过与 Posgres 控制台中的 SQL 语句相同的 INSERT 也是如此。
我有一个tableclients
大致定义为
CREATE TABLE clients (
id serial primary key,
name varchar
);
ALTER TABLE clients ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Allow client_admin to create new record if none exist" ON clients
FOR INSERT TO authenticated
WITH CHECK (
auth.is_user_in_group(auth.uid(), 'client_admin')
AND auth.client_ids() IS NULL
);
我的测试如下所示
// Given
const newUser = await createUser({
email: 'new_client+test@example.com',
})
await logInAs(newUser)
// When
const { data, error } = await anonClient
.from('clients')
.insert([generateClient({}).record])
注意:generateClient(...)
函数只生成一个带有随机数据的对象,不做任何插入。
插入语句失败
{"code": "42501", "details": null, "hint": null, "message": "new row violates row-level security policy for table \"clients\""}
即使我在 DataGrip 中打开控制台并执行
SET "request.jwt.claim.sub" TO '6aab88c8-6cc9-48fa-a90a-d45bfdc4a055';
SET ROLE authenticated;
INSERT INTO clients(name) VALUES (gen_random_uuid());
INSERT INTO clients(name) VALUES (gen_random_uuid());
第一次插入有效,而第二次插入失败。
为了让这个实验干净利落,我什至尝试了以下策略
CREATE POLICY "Allow client_admin to create new record if none exist" ON clients
FOR INSERT TO authenticated
WITH CHECK (
true
);
我什至尝试删除所有其他政策以确保它们不会以某种方式干扰。
关于我可能在哪里犯错的任何想法?
就像经常发生的那样,在 SO 上发帖后我几乎立即找到了答案。
我一直在阅读 SQL 查询日志,发现 supabase 也会在插入后立即尝试 SELECT 数据。
大致像
INSERT INTO clients(name) VALUES (gen_random_uuid()) RETURNING clients.*;
我有一个触发器可以将新记录插入 client_users
table 并影响 SELECT 策略。
显然这里发生的是:
TRANSACTION STARTS
INSERT to clients
RETURNING clients.* <--- FAILS RLS AND REVERTS TRANSACTION
INSERT to client_users <--- Should let SELECT RLS work, but fails due to order of operations
对于遇到同样问题的人来说,似乎有两种选择:
- 配置SELECT策略
- 做没有return任何信息的supabase插入
const { data, error } = await anonClient
.from('clients')
.insert(generateClient({}).record, {
returning: 'minimal',
})
我正在 supabase 中实现一个身份验证框架,它支持具有各种权限的多个角色,因此为不同的场景创建多个策略。
我的所有策略都包含一组集成测试以确保连续性。
我面临的一个特殊问题是来自 supabase JS API 的 INSERT 语句由于行级验证而失败,即使通过与 Posgres 控制台中的 SQL 语句相同的 INSERT 也是如此。
我有一个tableclients
大致定义为
CREATE TABLE clients (
id serial primary key,
name varchar
);
ALTER TABLE clients ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Allow client_admin to create new record if none exist" ON clients
FOR INSERT TO authenticated
WITH CHECK (
auth.is_user_in_group(auth.uid(), 'client_admin')
AND auth.client_ids() IS NULL
);
我的测试如下所示
// Given
const newUser = await createUser({
email: 'new_client+test@example.com',
})
await logInAs(newUser)
// When
const { data, error } = await anonClient
.from('clients')
.insert([generateClient({}).record])
注意:generateClient(...)
函数只生成一个带有随机数据的对象,不做任何插入。
插入语句失败
{"code": "42501", "details": null, "hint": null, "message": "new row violates row-level security policy for table \"clients\""}
即使我在 DataGrip 中打开控制台并执行
SET "request.jwt.claim.sub" TO '6aab88c8-6cc9-48fa-a90a-d45bfdc4a055';
SET ROLE authenticated;
INSERT INTO clients(name) VALUES (gen_random_uuid());
INSERT INTO clients(name) VALUES (gen_random_uuid());
第一次插入有效,而第二次插入失败。
为了让这个实验干净利落,我什至尝试了以下策略
CREATE POLICY "Allow client_admin to create new record if none exist" ON clients
FOR INSERT TO authenticated
WITH CHECK (
true
);
我什至尝试删除所有其他政策以确保它们不会以某种方式干扰。
关于我可能在哪里犯错的任何想法?
就像经常发生的那样,在 SO 上发帖后我几乎立即找到了答案。
我一直在阅读 SQL 查询日志,发现 supabase 也会在插入后立即尝试 SELECT 数据。
大致像
INSERT INTO clients(name) VALUES (gen_random_uuid()) RETURNING clients.*;
我有一个触发器可以将新记录插入 client_users
table 并影响 SELECT 策略。
显然这里发生的是:
TRANSACTION STARTS
INSERT to clients
RETURNING clients.* <--- FAILS RLS AND REVERTS TRANSACTION
INSERT to client_users <--- Should let SELECT RLS work, but fails due to order of operations
对于遇到同样问题的人来说,似乎有两种选择:
- 配置SELECT策略
- 做没有return任何信息的supabase插入
const { data, error } = await anonClient
.from('clients')
.insert(generateClient({}).record, {
returning: 'minimal',
})