I want to give a group of users selective access only to particular columns of an Application due a privacy concern. So, when user types ”’SELECT *”’ on restricted table, he could only see allowed columns.
What I want to achieve:
- Hide particular columns of a table from particular user group
- "SELECT *" works as usual, but hiding columns, which is not allowed
- DDL for the underlying table should not be forbidden, even if it could temporarily break the view (it’s okay to fix it later)
Let’s say:
- the group name is "restricted_group"
- the table is "users" (id, description, password)
The goal is:
When user from "restricted_group" does SELECT * FROM users, he must see only "id", "description" fields.
I tried two ways:
- Using views to underlying table:
CREATE VIEW restricted_view AS
SELECT "id", "description" FROM users;
GRANT SELECT ON restricted_view to restricted_group;
It does the job, but it PREVENTS any DDL on the table "users" due to Postgres’s restriction "cannot alter table because other objects depend on it".
Very strange behaviour in Postgres for me, because in Oracle it could just make view invalid, but not prevented DDL.
Using CASCADE or recreating VIEW is not feasible as a part of this task.
- Using explicit GRANT access to columns:
GRANT SELECT ("ID", "desc") ON users TO restricted_group;
It forbids users to make "SELECT * users" and requires to explicidly list all allowed columns, which isn’t user friendly. Because instead of getting data fast, user should check any column for access first.
Please, advise me a solution, which would met all initial requirenments?
2
Answers
There is none.
You have insisted on the following requirements:
This set of requirements are simply incompatible.
The obvious solution is to recreate the view when required, but you don’t say why that isn’t an option for you.
Postgres doesn’t completely restrict modification of tables that feed views, just the ones that would break the view. You can by all means add/change/remove table columns as long as you’re not mutating the ones that something else depends on. It’s not just views, but also foreign key references, any
pg_depend
orpg_constraint
entry.If you want a breakable view, or to simply decouple it from the underlying table, use a plain SQL table- or set-returning function, or put one between the view and the source table:
As you observed, a regular, direct view will be tied to the table via dependency, blocking some alterations:
An intermediate function removes that dependency:
This will continue to work as long as the types found in the table can be coerced to what the function is supposed to return.
fiddle