我在supabase中实现了一个身份验证框架,它支持具有不同权限的多个角色,从而为不同的场景创建多个策略。
我的所有策略都包含了一组集成测试,以确保连续性。
我面临的一个特殊问题是,supabase JS中的INSERT语句由于行级验证而失败,即使通过与Posgres控制台中的SQL语句相同的INSERT语句也是如此。
我有一个表clients
,大致定义为
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(...)
函数只生成具有随机数据的对象,不执行任何插入操作。
该insert语句在
{"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
);
我甚至试图删除所有其他政策,以确保它们不会以某种方式干预。
知道我在哪里会犯错误吗?
发布于 2022-04-19 15:15:25
就像经常发生的那样,几乎是在发完帖子之后,我就想出了答案。
我一直在阅读SQL查询日志,发现supabase还会尝试在insert之后立即选择数据。
大致看上去
INSERT INTO clients(name) VALUES (gen_random_uuid()) RETURNING clients.*;
我有一个触发器,该触发器将一个新记录插入到client_users
表并影响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
对于那些面临同样问题的人来说,似乎有两种选择:
const { data, error } = await anonClient
.from('clients')
.insert(generateClient({}).record, {
returning: 'minimal',
})
https://stackoverflow.com/questions/71926947
复制相似问题