Permission denied for relation <table_name> - postgresql

So I'm making this app and I'm using Postgres and I've already created a database, a user and a password and granted all privileges on the database to the user I've created.
The thing is, when I switch the database in psql using \c <database_name> I get in just fine and can use queries on it.
But when I run psql using postgres://user_name:password#localhost:5432/databasename on terminal and try to select * from the <table_name> it gives me this message
permission denied for relation <table_name>
Can you please tell me what to do, I've had this problem before and I had to create another database or change the user but I want a better solution please.
PS: I've tried to use this :
GRANT ALL PRIVILEGES ON TABLE <table_name> to <user_name>
This is how I created and accessed my database:
rawan95=# create database food ;
CREATE DATABASE
rawan95=# create user meal with password '123';
CREATE ROLE
rawan95=# grant all privileges on database food to meal;
GRANT
rawan95=# \c food
You are now connected to database "food" as user "rawan95".
After that, I've built it using
food=# \i src/database/db_build.sql
BEGIN
DROP TABLE
CREATE TABLE
INSERT 0 1
COMMIT
Then I selected data from the table just fine, but when I try to access it using this, I get an error: psql postgres://meal:123#localhost:5432/food
food=> select * from foods;
ERROR: permission denied for relation foods

You are granting the privileges before you create the tables.
As there are no tables at that moment nothing is granted. The tables you created are not owned by the user meal but the user rawan95 (which the \c command told you).
Plus: granting "all privileges" on a database, does not grant any select privilege. As documented in the manual "all privileges" are: CREATE, CONNECT, TEMPORARY, TEMP. The CREATE privilege would allow the user meal to create tables in that database.
If you want all those tables to be owned by the user meal you need to run your setup script after you connected as the user meal (the \c command did not change the current user)
If you do want rawan95 to be the owner of the tables, you need to either grant the select privilege after creating all tables:
grant select on all tables in schema public to meal;
Or, you can change the default privilege before creating the tables (before running db_build.sql), so that they are applied to all tables in the future:
alter default privileges in schema public
grant select on all tables to meal;
The alter default privileges only has an effect for tables that are created after that. So to fix your current setup, you need to first grant select on the existing tables, and the change the default privileges for all tables that are created in the future.

Have you granted usage on the schema? Without that the table permissions are useless.
GRANT USAGE ON SCHEMA schema_name TO username
EDIT: Based on comment thread below we have established.
The table is in public schema.
The table belongs to rawan95 but the schema does not (public schema belongs to root postgres user).
The OP is attempting to connect and access the table as user 'meal' they have granted table permissions using the rawan95 user but are unable to grant schema permissions.
From the above, the problem could still be that the user 'meal' does not have usage on the public schema. If you are on Linux the quickest way to sort this is to switch to the super user to make this change from terminal:
sudo -u postgres psql -c "GRANT USAGE ON SCHEMA public TO meal"
FURTHER EDIT - having read your new clarification this is not correct (or at least not useful). The issue is as pointed out by the other answerer that you didn't have a table at the time you did the grant.

Related

Postgres Grant CRUD on DATABASE to USER

I have an application which uses a postgres database. I have a superadmin user. Now I need two more users: One "application-user" with CRUD-privileges and one with ALTER and CREATE-privileges (to apply migrations). These are all users I need, because the application has its own User-Access management and it is not at all planned to change that.
I want something like: GRANT SELECT, INSERT, UPDATE, DELETE ON DATABASE MyDatabase TO myuser
I've read here that postgres provides pre defined roles. This is good - but these roles apply globally (as pointed out in one comment). MyDatabase is on public schema which becomes problematic because some system tables are on public too - and I don't want myuser to be able to read from or write to these.
I'd be fine with GRANT pg_read_all_data, pg_write_all_data ON DATABASE MyDatabase TO myuser but this doesn't work.
As I'll not change these privileges often I'd even be fine with GRANT pg_read_all_data ON MyDatabase.MyTable TO myuser as well. But this doesn't work either.
Any ideas on this?
There are no ALTER and CREATE privileges in PostgreSQL. The database user that should be able to run ALTER and CREATE statements will have to be the owner of the database objects. If you already have objects owned by a different user, you will have to change the ownership.
For the other user, you will have to grant privileges on each and every object. Privileges on the database won't help – there is no inheritance of privileges between objects. Don't forget to grant USAGE on the schemas.
I recommend that you create more schemas than public. If you have a separate schema for your application's objects, you can use statements like
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA myapp TO someuser;

Safely drop a user in Postgres

I am very new to Postgress security topic. I have used the following commands to create a user.
CREATE USER myuser WITH PASSWORD 'PASSWORD';
GRANT CONNECT ON DATABASE "MyDB" TO myuser;
GRANT ALL PRIVILEGES ON DATABASE "MyDB" TO myuser;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO myuser;
Immediately afterwards I wanted to drop this user by I receive an error similar to:
ERROR: role "tempuser" cannot be dropped because some objects depend on it
DETAIL:
privileges for view myView
privileges for table myTable
... [rest of views and tables]
It kinda scares me. How can I safely drop a user without affecting the data and other objects in database?
Reverse each of your GRANT with a corresponding REVOKE.
It kinda scares me. How can I safely drop a user without affecting the data and other objects in database?
If you consider a REVOKE to be "affecting the objects", then you can't drop the user without affecting the objects. Why does this scare you? As you can see, the system won't let you do this implicitly, so what is there to be scared of?

postgreSQL: How to use ROLE to allow full access to all users part of a given role (without using SET ROLE prior accessing a table for instance)

I'm coming to postgreSQL with a SQL Server background and was naively applying the same concepts to postgreSQL in order to allow different users to share 'by default' some objects within a database.
This is what I did:
CREATE DATABASE testdb;
CREATE ROLE testdb_role_full INHERIT;
GRANT ALL PRIVILEGES ON DATABASE testdb TO testdb_role_full;
CREATE USER user1 INHERIT;
GRANT testdb_role_full TO user1;
CREATE USER user2 INHERIT;
GRANT testdb_role_full TO user2;
Once done, I created a table t1 using the user1.
Then, I tried, as user2, to read the t1 table and I received a "permission denied error"... :-(
By reading the documentation, it seems that I have to issue a SET ROLE testdb_role_full first so as to act as the testdb_role_full.
However, this is not really that I want. I do not want the user to be aware of this.
So my question:
Is there any way to make this work?
Thanks a lot,
José
You've granted some privileges on the database, but that doesn't mean any user with the role testdb_role_full would have all privileges on all objects inside that database. To quote from the documentation:
When an object is created, it is assigned an owner. The owner is normally the role that executed the creation statement. For most kinds of objects, the initial state is that only the owner (or a superuser) can do anything with the object. To allow other roles to use it, privileges must be granted.
So after the user1 created the table t1, he is the owner and only he has the privileges on it. He would need to run
GRANT ALL PRIVILEGES ON TABLE t1 TO testdb_role_full;
then user2 would be able to access it as well (without having to switch any roles - that's only necessary when it has the NOINHERIT attribute on the role).
If you don't want your users to have to execute GRANT each time they create a new object in the database, you can alter the default privileges that will be applied whenever an object is created by user2:
ALTER DEFAULT PRIVILEGES FOR user2
GRANT ALL PRIVILEGES ON TABLES TO testdb_role_full;
Notice these specify the initial value only, and user2 could revoke the privileges on his tables if he wanted to prevent others from seeing them.

Postgres role with usage privilige but not DELETE

I have a postgres instance with a user root that has full admin privileges.
I have two databases db1 and db2.
For every database, I would like to have two users dbN_user and dbN_admin. dbN_user will be the used by my application, and dbN_admin will be used for migrations that change the table structure.
No rows are ever deleted by the application, and I would like to enforce that with user privileges.
db1_user should be able to connect to db1, and be able to SELECT, INSERT and UPDATE, but not DELETE.
db1_admin should have additional privileges to DELETE, CREATE TABLE, ALTER TABLE.
What are the SQL statements to set this up?
dbN_admin would be the owner of the objects, so that user would have all privileges automatically.
You need to GRANT the privileges for dbN_user on the tables and other objects themselves, not on the database.
Just add the correct GRANT statements after the CREATE TABLE statements in the SQL script that populates the database.
You need to GRANT the USAGE privilege on the schema that contains the objects to dbN_user as well.
There is the possibility to define default privileges in a database:
ALTER DEFAULT PRIVILEGES FOR dbN_admin
GRANT SELECT, INSERT, UPDATE ON TABLES
TO dbN_user;
This will grant the privileges automatically whenever dbN_admin creates a new table (but it does not affect tables created before the ALTER DEFAULT PRIVILEGES command).
admin:
create user db1_admin;
create schema app_relations;
alter schema app_relations owner to db1_admin;
app:
create user db1_user;
grant CONNECT ON DATABASE db1 to db1_user; --only if you have restricted connections on db previously
grant usage on schema app_relations to db1_user;
grant select,insert,update on all tables in schema app_relations to db1_user;

Postgres create database user with grant access to schema only

I have a database with a template_schema.I cloned this template schema and created a database user with password. I need to provide access to cloned schema only, for the created user.
SELECT clone_schema('my_template_schema','john_smith_gmail_com');
CREATE USER john_smith_gmail_com WITH PASSWORD 'mypassword';
Upto this Ok. Then I need to grant access to this user for this cloned schema(john_smith_gmail_com) only
Method :1
I tried to revoke all privileges on all tables of cloned schema(john_smith_gmail_com) for the user and grant select to the user. But my question is, can this user get SELECT access on other schema tables?
REVOKE ALL ON ALL TABLES IN SCHEMA john_smith_gmail_com FROM john_smith_gmail_com;
GRANT SELECT ON ALL TABLES IN SCHEMA john_smith_gmail_com TO john_smith_gmail_com;
Method :2
Create a role with only SELECT access and assign or grant this role to newly created user. If I do this, for which schema I grant access,because I clone schema dynamically?
Which method is best one?
From postgresql version 9.0 and forward, the best way is probably to use ALTER DEFAULT PRIVILEGES.
...the default privileges for any object type normally grant all grantable permissions to the object owner, and may grant some privileges to PUBLIC as well. However, this behavior can be changed by altering the global default privileges with ALTER DEFAULT PRIVILEGES.
So if all users like "john_smith_gmail_com" should only have SELECT access to tables in "their own" schema, after creating the schema and user, you can run:
ALTER DEFAULT PRIVILEGES IN SCHEMA john_smith_gmail_com GRANT SELECT ON TABLES TO john_smith_gmail_com;