SQL Server - Are permissions on tables required? - sql-server

My question again to be more specific:
How can I modify data through a view and don't have to grant SELECT-Permissions on the table?
I am designing and developing a new database at the company i am working for.
The business rules say, that users are allowed to access specific rows in tables only.
So I use views to check the permissions of the user and return only those records, the user has access to.
So far so god.
But, I have to check the permissions also on INSERT and UPDATE and DELETE with INSTEAD-of-Triggers. Because the rows a User can SELECT may not be those, he can modify.
My problem is:
When I have an view and grant SELECT, INSERT, UPDATE and DELETE Permissions, it doesn't work. When I insert into this view, SQL Server wants INSERT-Permission at the base table. That wouldn't be a problem. But when I update or delete rows through the view, SQL Server wants SELECT and UPDATE/DELETE permissions granted on the base table.
I don't want to give SELECT-rights on the table.
Thanks
Chris

I'm thinking at:
1/ Restrict VIEW rows by adding in its definition a condition like this:
WHERE UserName = SUSER_SNAME()
or
WHERE UserName = CURRENT_USER()
or
2/ Using INSTEAD OF triggers on the involved view.
P.S. Indeed, CREATE VIEW WITH EXECUTE is not allowed. Thank you for your messages.

Related

Snowflake : List out all roles and their access level to each Database objects

I need to get all the roles and their access to each database objects whether is it Read access or Write access
In Snowflake, I tried as below
show roles
select * from table(RESULT_SCAN (LAST_QUERY_ID()));
I'd like to show ALL grants for ALL roles in one table. My best guess would be to write a procedure that iterates through all the role names, executes the above code, and outputs the result to a table.
Is there a better way of doing this?
I also checked this view GRANTS_TO_ROLES , but not sure if this gives me all the roles for all the database

Is it possible to protect columns of a view in snowflake?

I'm working at a company where one team manages the databases and others use tables / views from there. From time to time, views get refactored which might break things for other teams.
Is it possible to protect some columns so that those cannot simply be renamed / dropped? Or at least have a log message telling the person who wants to do it that another team depends on it?
In Snowflake, only users with roles who have privileges to update a view by changing its definition are able to make changes on the specified view. If a specific role has privileges to replace view definition, there is no mechanism to stop them from renaming or dropping columns.
You can see the logs in QUERY_HISTORY function in Snowflake Information_schema. The functions gives extensive information on which user ran the query and the time it ran. A query like below would bring the appropriate information:
select user_name, role_name, query_text, start_time, end_time from table(information_schema.query_history())
where query_text ilike '%replace view %'
order by start_time desc;
The privilege to alter a view is all or nothing. It does not restrict which columns the role can or cannot alter, remove, add, etc. However, since Snowflake allows using views as part of another view, this can form part of your organization's overall approach to do what you're seeking.
For example, create a base view that has all the protected columns. Tightly control access to which roles can alter the base view. From the base view, create views on top that less privileged roles can alter.

update granted on view, but cannot update underlying table, why?

I have a table and a view. They are in different schema, but have the same owner:
according to sys.objects: principal_ID = null, schema_ID is 1 and 4
according to sys.schemas: both schemas have the same principal_id (1 = dbo)
The view is simply select a,b,c from table
Now a user has been given the right to select, insert, update and delete rows from the view. He has no rights on the underlying table.
In fact, the user can select data. But if he wants to change anything, we get two errors: 'No SELECT granted on table" and "No UPDATE granted on table".
What is going wrong here?
Update-able views are only update-able if you grant the permissions on the table, too:
Requires UPDATE, INSERT, or DELETE permissions on the target table, depending on the action being performed.
See the TechNet article Modify Data Through a View.
The solution was that I was accessing the view with the C# SqlCommandBuilder class. But what I did not know is that the CommandBuilder tries to be "intelligent" and analyzes the view. It then creates statements which access the underlying tables, instead of the view. The only solution is to circumvent the SqlCommandBuilder.
I stumbled over the problem also this year, here is another link:
https://stackoverflow.com/a/31231563/2504785

Restrict access to certain rows in table based on user

In SQL Server, how do I restrict access to certain rows (hide data) in tables based on the users identity?
The basic / normal way to do this would be:
prevent that user (or group) from accessing the base table
define a view on top of that table that shows only the rows these users are supposed to see
give those users SELECT permission on the view

inserting into a view in SQL server

I have a SQL Server as backend and use ms access as frontend.
I have two tables (persons and managers), manager is derived from persons (a 1:1 relation), thus i created a view managersFull which is basically a:
SELECT *
FROM `managers` `m`
INNER JOIN `persons` `p`
ON `m`.`id` = `p`.`id`
id in persons is autoincrementing and the primary key, id in managers is the primary key and a foreign key, referencing persons.id
now i want to be able to insert a new dataset with a form in ms access, but i can’t get it to work. no error message, no status line, nothing. the new rows aren’t inserted, and i have to press escape to cancel my changes to get back to design view in ms access.
i’m talking about a managers form and i want to be able to enter manager AND person information at the same time in a single form
my question is now: is it possible what i want to do here? if not, is there a “simple” workaround using after insert triggers or some lines of vba code?
thanks in advance
The problem is that your view is across several tables. If you access multiple tables you could update or insert in only one of them.
Please also check the MSDN for more detailed information on restrictions and on proper strategies for view updates
Assuming ODBC, some things to consider:
make sure you have a timestamp field in the person table, and that it is returned in your managers view. You also probably need the real PK of the person table in the manager view (I'm assuming your view takes the FK used for the self-join and aliases it as the ID field -- I wouldn't do that myself, as it is confusing. Instead, I'd use the real foreign key name in the managers view, and let the PK stand on its own with its real name).
try the Jet/ACE-specific DISTINCTROW predicate in your recordsource. With Jet/ACE back ends, this often makes it possible to insert into both tables when it's otherwise impossible. I don't know for certain if Jet will be smart enough to tell SQL Server to do the right thing, though.
if neither of those things works, change your form to use a recordsource based on your person table, and use a combo box based on the managers view as the control with which you edit the record to relate the person to a manager.
Ilya Kochetov pointed out that you can only update one table, but the work-around would be to apply the updates to the fields on one table and then the other. This solution assumes that the only access you have to these two tables is through this view and that you are not allowed to create a stored procedure to take care of this.
To model and maintain two related tables in access you don’t use a query or view that is a join of both tables. What you do is use a main form, and drop in a sub-form that is based on the child table. If the link master and child setting in the sub-form is set correctly, then you not need to write any code and access will insert the person’s id in the link field.
So, don’t use a joined table here. Simply use a form + sub-form setup and you be able to edit and maintain the data and the data in the related child table.
This means you base the form on the table, and not a view. And you base the sub-form on the child table. So, don't use a view here.

Resources