How to allow a user to see a subset of a table or view - postgresql

I have a view in a private schema with several lets say company_id's. For a special use case I want to allow one company to see a subset of this table (for its own data). So I have create a role and a schema 'company_123' and I have created a view in this schema like
create view company_123.transactions_v as
select * from business.all_transactions_v
where company_id = 123;
But unfortunately this view is empty as the user 'company_123' has no select rights on the original view. How could I achieve this requirement?

You will have to grant SELECT permissions to the user on your table.
You can slice the visible rows and columns to the user though and you should be able to solve your problem.

Related

Is it possible to create multi scheme view in RedShift and how?

I have multipale schemes in Redshift that are similar to one another
basically for every new customer a new scheme is created.
in each scheme i have products table: product_id , product_name
and i have one view that present the scheme_name and scheme_id.
I need to create a single view that will show all the product_id and product_name with the scheme_id next to it.
so in the end i will have one view with all products from all schemes and the scheme id so i will know to which one it belongs.
how can i create a dynamic view for it?
Within a database you specify a schema then a "." then the table.
e.g.
create view views.demo
as
select *
from schema1.table1 as a
join schema2.table2 as b on a.id=b.table1_id
you can create this dynamically OUTSIDE of redshift using python or similar

Replacing schema name when sharing sql script with other users

When collaborating with colleagues I need to change the schema name every time I receive a SQL script (Postgres).
I am only an ordinary user of a corporate database (no permissions to change anything). Also, we are not allowed to create tables in PUBLIC schema. However, we can use (read-only) all the tables from BASE schema.
It is cumbersome for the team of users, where everybody is creating SQL scripts (mostly only for creating tables), which need to be shared amongst others. Every user has its own schema.
Is it possible to change the script below, where I will share the script to another user without the need for the other user to find/replace the schema, in this case, user1?
DROP TABLE IF EXISTS user1.table1;
CREATE TABLE user1.table1 AS
SELECT * FROM base.table1;
You can set the default schema at the start of the script (similar to what pg_dump generates):
set search_path = user1;
DROP TABLE IF EXISTS table1;
CREATE TABLE table1 AS
SELECT * FROM base.table1;
Because the search path was change to contain user1 as the first schema, tables will be searched in that schema when dropping and creating. And because the search path does not include any other schema, no other schema will be consulted.
If you
However the default search_path is "$user", public which means that any unqualified table will be searched or created in a schema with the same name as the current user.
Caution
Note that a DROP TABLE will drop the table in the first schema found in that case. So if table1 doesn't exist in the user's schema, but in the public schema, it would be dropped from the public schema. So for your use-case setting the path to exactly one schema might be more secure.

Postgres GRANT not applied on parent

I'm in trouble with grant in postgresql (version 9.3).
I'm trying to restrict a ROLE 'client_1'. I want it to be able to do only select for one table. But there is inheritance between tables.
Here is my table structure:
CREATE TABLE public.table_a (...);
CREATE TABLE table_a_partitions.child_1 (...) INHERITS (public.table_a);
CREATE TABLE table_a_partitions.child_2 (...) INHERITS (public.table_a);
GRANT SELECT ON table_a_child_1 TO client_1;
It's okay when I do a select on child_2, there is an error, but if I do a SELECT * FROM table_a; for example it also reads the forbidden table child_2. I would my client access only child_1 (and some other in the future) results when he does SELECT * FROM table_a;.
Is there a simple way to solve this problem ?
Thank you
You would need to use a VIEW in PostgreSQL 9.3 to solve this problem. If you upgrade to 9.5, however, you could use row-level security.
As a note as to why, the grant check only occurs on the level of the initial relation queried. This means if you query a view, you need access to the view's contents, but the view owner (NOT YOU) needs access to the underlying relations. This allows a view to be useful for information hiding. Similarly with inheritance, this structure allows you to forbid rows to be inserted or queried directly from partitions of a table, but to allow different queries via the parent table. So this is a consequence of design priorities, not a bug.
Before row-level security, you would basically create a view and fold in user privilege criteria into the view (with partitioning/inheritance this is also a good idea for other reasons since your insert/update/delete triggers can return exactly what the db would do even though it cannot on a table).
As for row-level security, PostgreSQL 9.5 does allow you to specify row-level policies (conditions that get appended to insert/select/update/delete queries) and that provides something a little more manageable in some cases than the view approach.

Sybase TSQL access to table or view

When I select all data from table/view person from database city I'll do it like this:
select * from city..person
ASE then substitutes the * to all the columns and .. for .dbo. and the query will be this:
select name, age, sex from city.dbo.person
If I have another view person created by another user (lets call it boss), and I want to access that view I need to make a select like this:
select * from city.boss.person
Is there a way to make the city..person to be city.boss.person instead of city.dbo.person?
The naming convention in Sybase to identify a table/view is [[database.]owner.]table_or_view_name, which means that the database and owner qualifiers are optional.
If you don't specify them, database is expanded to the current database and owner is expanded to the current user.
In your example, city..person expanded to city.dbo.person, because you're running under dbo user. The only way to have ASE expanding city..person to city.boss.person, is running the query under the boss user.

Can I reference a table in a view from a stored procedure?

I've created a view on 3 tables in my database, they are as follows:
Activity
ActivityRole
aspnet_UsersInRoles
I am trying to grab the combination of what's in Activity and ActivityRole, if the UserId I pass in is a member of the role specified as required in the Activity Role.
I'm creating a view, because I want to generate an object off of the view that is called Activity that has fields from Activity and ActivityRole.
My first attempt was to create the view that INNER JOINED Activity to ActivityRole and ActivityRole to the UserRoles on Activity.ActivityId = ActivityRole.ActivityId and ActivityRole.RoleId = aspnet_UsersInRoles.RoleId
Now I want to only pull back records by a UserId located in the aspnet_User_UserRoles table.
My inclination is to write a stored procedure which does:
SELECT * From MyView WHERE aspnet_UsersInRoles.UserID = #UserID
However I cannot reference the aspnet_UsersInRoles table in the view via the stored procedure.
Is my approach totally wrong?
Thank you for any assistance.
You should look at a view as you look at a table, something with rows and columns. From the outside you see just the columns you defined in the view, not the underlying columns from the tables you created the view from. So in your case, MyView does not have a column named aspnet_UsersInRoles.UserId.
To be able to query on this column, you should include it in your view. Then you can do something like:
SELECT * FROM MyView v WHERE v.UserId = #UserId