diff --git a/src/lib/PostgresMetaPolicies.ts b/src/lib/PostgresMetaPolicies.ts index 72d3157b..6632fb01 100644 --- a/src/lib/PostgresMetaPolicies.ts +++ b/src/lib/PostgresMetaPolicies.ts @@ -142,7 +142,11 @@ CREATE POLICY ${ident(name)} ON ${ident(schema)}.${ident(table)} const nameSql = name === undefined ? '' : `${alter} RENAME TO ${ident(name)};` const definitionSql = definition === undefined ? '' : `${alter} USING (${definition});` const checkSql = check === undefined ? '' : `${alter} WITH CHECK (${check});` - const rolesSql = roles === undefined ? '' : `${alter} TO ${roles.map(ident).join(',')};` + // An empty array means "all roles", which is the default `create` applies. + const rolesSql = + roles === undefined + ? '' + : `${alter} TO ${(roles.length === 0 ? ['public'] : roles).map(ident).join(',')};` // nameSql must be last const sql = `BEGIN; ${definitionSql} ${checkSql} ${rolesSql} ${nameSql} COMMIT;` diff --git a/test/lib/policies.ts b/test/lib/policies.ts index ef7eccbc..257b6929 100644 --- a/test/lib/policies.ts +++ b/test/lib/policies.ts @@ -188,3 +188,24 @@ test('retrieve, create, update, delete', async () => { }, }) }) + +test('update roles to an empty array falls back to public', async () => { + let res = await pgMeta.policies.create({ + name: 'test empty roles policy', + schema: 'public', + table: 'memes', + roles: ['postgres'], + }) + const policyId = res.data!.id + expect(res.data!.roles).toStrictEqual(['postgres']) + + // An empty array means "all roles" — the same default `create` applies. + // `name` is typed as required even though `update` treats it as optional, and + // renaming a policy to its own name errors, so it has to be omitted here. + res = await pgMeta.policies.update(policyId, { roles: [] } as any) + + expect(res.error).toBeNull() + expect(res.data!.roles).toStrictEqual(['public']) + + await pgMeta.policies.remove(policyId) +})