Skip to content

Commit 406df42

Browse files
committed
Doc: fix oversimplified example for CREATE POLICY.
As written, this policy constrained only the post-image not the pre-image of rows, meaning that users could delete other users' rows or take ownership of such rows, contrary to what the docs claimed would happen. We need two separate policies to achieve the documented effect. While at it, try to explain what's happening a bit more fully. Per report from Олег Самойлов. Back-patch to 9.5 where this was added. Thanks to Stephen Frost for off-list discussion. Discussion: https://postgr.es/m/3298321532002010@sas1-2b3c3045b736.qloud-c.yandex.net
1 parent e768869 commit 406df42

File tree

1 file changed

+33
-9
lines changed

1 file changed

+33
-9
lines changed

doc/src/sgml/ddl.sgml

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,33 +1623,57 @@ CREATE POLICY account_managers ON accounts TO managers
16231623
USING (manager = current_user);
16241624
</programlisting>
16251625

1626+
<para>
1627+
The policy above implicitly provides a <literal>WITH CHECK</literal>
1628+
clause identical to its <literal>USING</literal> clause, so that the
1629+
constraint applies both to rows selected by a command (so a manager
1630+
cannot <command>SELECT</command>, <command>UPDATE</command>,
1631+
or <command>DELETE</command> existing rows belonging to a different
1632+
manager) and to rows modified by a command (so rows belonging to a
1633+
different manager cannot be created via <command>INSERT</command>
1634+
or <command>UPDATE</command>).
1635+
</para>
1636+
16261637
<para>
16271638
If no role is specified, or the special user name
16281639
<literal>PUBLIC</literal> is used, then the policy applies to all
1629-
users on the system. To allow all users to access their own row in
1630-
a <literal>users</> table, a simple policy can be used:
1640+
users on the system. To allow all users to access only their own row in
1641+
a <literal>users</literal> table, a simple policy can be used:
16311642
</para>
16321643

16331644
<programlisting>
16341645
CREATE POLICY user_policy ON users
16351646
USING (user_name = current_user);
16361647
</programlisting>
16371648

1649+
<para>
1650+
This works similarly to the previous example.
1651+
</para>
1652+
16381653
<para>
16391654
To use a different policy for rows that are being added to the table
1640-
compared to those rows that are visible, the <literal>WITH CHECK</>
1641-
clause can be used. This policy would allow all users to view all rows
1642-
in the <literal>users</> table, but only modify their own:
1655+
compared to those rows that are visible, multiple policies can be
1656+
combined. This pair of policies would allow all users to view all rows
1657+
in the <literal>users</literal> table, but only modify their own:
16431658
</para>
16441659

16451660
<programlisting>
1646-
CREATE POLICY user_policy ON users
1647-
USING (true)
1648-
WITH CHECK (user_name = current_user);
1661+
CREATE POLICY user_sel_policy ON users
1662+
FOR SELECT
1663+
USING (true);
1664+
CREATE POLICY user_mod_policy ON users
1665+
USING (user_name = current_user);
16491666
</programlisting>
16501667

16511668
<para>
1652-
Row security can also be disabled with the <command>ALTER TABLE</>
1669+
In a <command>SELECT</command> command, these two policies are combined
1670+
using <literal>OR</literal>, with the net effect being that all rows
1671+
can be selected. In other command types, only the second policy applies,
1672+
so that the effects are the same as before.
1673+
</para>
1674+
1675+
<para>
1676+
Row security can also be disabled with the <command>ALTER TABLE</command>
16531677
command. Disabling row security does not remove any policies that are
16541678
defined on the table; they are simply ignored. Then all rows in the
16551679
table are visible and modifiable, subject to the standard SQL privileges

0 commit comments

Comments
 (0)