I am trying to wrap my head around row level security in Postgres. Unfortunately the documentation is not very verbose on the matter. My problem is the following:
I have two tables: locations
and locations_owners
. There is a TRIGGER
set on INSERT
for locations, which will automatically add a new row to the locations_owners
table including the request.jwt.claim.sub
variable .
This works all just fine, however when I want to create a policy for DELETE
like this:
CREATE POLICY location_delete ON eventzimmer.locations FOR DELETE TO organizer USING(
(SELECT EXISTS (SELECT name FROM protected.locations_owners AS owners WHERE owners.name = name AND owners.sub = (SELECT current_setting('request.jwt.claim.sub', true))))
);
It will always evaluate to true, no matter the actual content. I know that I can call a custom procedure with SELECT
here, however I ended up with the following questions:
policy
? Can I access tables? Can I access procedures? The documentation says "Any SQL conditional expression" so SELECT EXISTS
should be finename
variable), however I have not found any documentation about what this actually doesuser_name
variable. Where does it come from? I believe it is the current role
which is executing the query, but how can I know?WITH CHECK
expression available for DELETE
? If I understand correctly, WITH CHECK
will fail
any row with invalid constraint, which is the behaviour I would prefer (because otherwise PostgREST will always return 204
)I am a little bit confused by the astonishingly missing amount of information in the (otherwise) very good documentation of PostgreSQL. Where is this information? How can I find it?
For the sake of completeness I have also attached the column definitions below:
CREATE TABLE eventzimmer.locations (
name varchar PRIMARY KEY NOT NULL,
latitude float NOT NULL,
longitude float NOT NULL
);
CREATE TABLE IF NOT EXISTS protected.locations_owners (
name varchar NOT NULL REFERENCES eventzimmer.locations(name) ON DELETE CASCADE,
sub varchar NOT NULL
);
Many of the questions will become clear once you understand how row level security is implemented: the conditions in the policies will automatically be added to the query, just as if you added another WHERE
condition.
Use EXPLAIN
to see the query plan, and you will see the policy's conditions in there.
So you can use any columns from the table on which the policy is defined.
Essentially, you can use anything in a policy definition that you could use in a WHERE
conditions: Function calls, subqueries and so on.
You can also qualify the column name with the table name if that is required for disambiguation. This can be used in the policy from your example: The unqualified name
is interpreted as owners.name
, so the test always succeeds. To fix the policy, use locations.name
instead of name
.
There is no magic user_name
variable, and I don't know where you get that from. There is, however, the current_user
function, which is always available and can of course also be used in a policy definition.
WITH CHECK
is a condition that the new row added by INSERT
or UPDATE
must fulfill. Since DELETE
doesn't add any data, WITH CHECK
doesn't apply to it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.