How to do it…

To revoke all rights on the table1 table from the user2 user, you must run the following SQL command:

REVOKE ALL ON table1 FROM user2;

However, if user2 has been granted another role that gives them some rights on table1, say role3, this command is not enough; you must also choose one of the following options:

Both choices are imperfect because of their side-effects: The former will revoke all the privileges associated to role3, not just the privileges concerning table1; the latter will revoke the privileges on table1 from all the other users that have been granted role3, not just from user2.

It is normally better to avoid damaging other legitimate users, so we opt for the first solution. The following is a worked example.

Using psql, display the list of roles that have been granted at least one privilege on table1 by issuing \z table1. For instance, you can obtain the following output (an extra column about column privileges has been removed from the right-hand side because it was not relevant here):

                   Access privileges
Schema | Name | Type | Access privileges | ...
--------+--------+-------+---------------------------+ ...
public | table1 | table | postgres=arwdDxt/postgres+| ...
| | | role3=r/postgres +| ...
| | | role5=a/postgres | ...
(1 row)

Then we check whether user2 is a member of any of those roles by typing \du user2:

           List of roles
Role name | Attributes | Member of
-----------+------------+---------------
user2 | | {role3, role4}

From the previous step, we notice that role3 had been granted the SELECT privilege (r for read) by the postgres user, so we must revoke it, as follows:

REVOKE role3 FROM user2;

We must also inspect role4. Even if it doesn't have privileges on table1, in theory it could be a member of one of the three roles that have privileges on that table. We issue \du role4 and get the following output:

            List of roles
Role name | Attributes | Member of
-----------+--------------+-----------
role4 | Cannot login | {role5}

Our suspicion was well founded: user2 can get the INSERT privilege (a for append) on table1, first via role4 and then via role5. So we must break this two-step chain as follows:

REVOKE role4 FROM user2;
This example may seem too unlikely to be true. We unexpectedly gain access to the table via a chain of two different role memberships, which was made possible by the fact that a non-login role, such as role4, was made a member of another non-login role, that is, role5. In most real-world cases, superusers will know very well whether such chains exist at all, so there will be no surprise; however, the goal of this recipe is to make sure that the user cannot access the table, meaning we cannot exclude less likely options.