The INSERT permission was denied on the object 'Driver' - tsql

I am trying to run the following script from SQL Server Management Studio:
INSERT [Truck].[Driver] ([DriverId], [CorporationId], [DriverNumber], [Name], [PhoneNumber])
VALUES (N'b78f90a6-ed6d-4f0e-9f35-1f3e9c516ca9', N'0a48eeeb-37f6-44de-aff5-fe9107d821f5', N'12', N'Unknown', NULL)
And I'm getting this error:
Msg 229, Level 14, State 5, Line 1
The INSERT permission was denied on the object 'Driver', database 'SuburbanPortal2', schema 'Truck'.
I can manually add this in edit mode and I get no errors. I have every permission I can think of set for my users. This is a local database logging in as a local user that I'm testing some data on so I could care less about security.
But, here are the settings for the database for my user:
Any suggestions?

-- Use master
USE msdb;
go
-- Make database
CREATE DATABASE SuburbanPortal2;
go
-- Use the database
USE SuburbanPortal2;
GO
-- Make schema
CREATE SCHEMA Truck AUTHORIZATION dbo;
go
-- Make table
CREATE TABLE Truck.Driver
(
[DriverId] uniqueidentifier,
[CorporationId] uniqueidentifier,
[DriverNumber] varchar(64),
[Name] varchar(128),
[PhoneNumber] varchar(12)
);
-- Add data
INSERT [Truck].[Driver] ([DriverId], [CorporationId], [DriverNumber], [Name], [PhoneNumber])
VALUES (N'b78f90a6-ed6d-4f0e-9f35-1f3e9c516ca9', N'0a48eeeb-37f6-44de-aff5-fe9107d821f5', N'12', N'Unknown', NULL);
GO
This code setups a sample database like you have. I have no issues with the insert.
Who is the owner of the schema??
If you want to hide tables from one database group and another, add your user to the database group.
Make the database group the owner of the schema. I think you might be having a schema ownership issue ...
Can you drill into database -> security -> schemas -> Truck, right click and show me the owner of the schema. Please post image.
Also, remove all database permissions from the user except for db_owner.

Related

Using CREATE SCHEMA AUTHORIZATION

Can I use CREATE SCHEMA AUTHORIZATION for something other than the current user's schema?
I can do the following:
CREATE USER MAIN_USER
IDENTIFIED BY main_user_pass;
GRANT CREATE SESSION TO MAIN_USER;
GRANT CREATE TABLE TO MAIN_USER;
ALTER SESSION SET CURRENT_SCHEMA = MAIN_USER;
Query 1:
SELECT USER FROM DUAL;
Result 1:
SYS
Query 2:
SELECT sys_context( 'userenv', 'current_schema') FROM dual;
Result 2:
MAIN_USER
I can do this:
CREATE SCHEMA AUTHORIZATION SYS
CREATE TABLE new_product
(color VARCHAR2(10) PRIMARY KEY);
Result:
Schema AUTHORIZATION created.
But when I try to do this, an error appears:
CREATE SCHEMA AUTHORIZATION MAIN_USER
CREATE TABLE new_product
(color VARCHAR2(10) PRIMARY KEY);
Result:
ORA-02421: missing or invalid schema authorization identifier
02421. 00000 - "missing or invalid schema authorization identifier"
*Cause: the schema name is missing or is incorrect in an authorization
clause of a create schema statement.
*Action: If the name is present, it must be the same as the current
schema.
The error message is pretty clear: you can't do that. From the documentation:
The schema name must be the same as your Oracle Database username.
Setting current_schema only changes the default schema name prepended to an object reference in a SQL command that isn't fully qualified, so after setting it to MAIN_USER, this command:
select * table table_a;
would be interpreted as
select * from main_user.table_a;
instead of
select * from sys.table_a;
Setting current_schema doesn't actually change your logged in identity or affect your privileges in any way, and if sys can't execute a command like that against another schema then nobody can do it.
Can I use CREATE SCHEMA AUTHORIZATION for something other than the current user's schema?
No, you can't. The documentation says:
Use the CREATE SCHEMA statement to create multiple tables and views and perform multiple grants in your own schema in a single transaction.
This statement lets you populate your schema ...
Specify the name of the schema. The schema name must be the same as your Oracle Database username.
You have to be connected as the schema owner, so user returns MAIN_USER. Just changing your current schema with ALTER SESSION SET CURRENT_SCHEMA is not sufficient.
It also says:
To issue a CREATE SCHEMA statement, you must have the privileges necessary to issue the included statements.
and you have granted CREATE TABLE so that should work once you connect as that user. But it means you can't rely on the privileged SYS user's CREATE ANY privs to bypass the schema grants, which might have been an advantage had it been allowed to work as you hoped; if you want your user to end up without those privileges you'll have to grant them, run CREATE SCHEMA as that user, then revoke them again. Or go back to individual CREATE object statements, which you can run for another user as SYS - but without the all-or-nothing single-transaction benefit you get from CREATE SCHEMA.

Moving a table from a database to another - Only insert missing rows

I have two databases that are alike, one called datastore and the other called datarestore.
datarestore is a copy of datastore which was created from a backup image. The problem is that I accidentally deleted a little too much data from datastore.
Both databases are located on different AWS instances and I typically connect to them using pgAdmin III or Python to create scripts that handle the data.
I want to get the rows that I accidentally deleted from datastore which are in datarestore into datastore. Does anyone have any idea of how this can be achieved. Both databases contain close to 1.000.000.000 rows and are on version 9.6.
I have seen some backup/import/restore options within pgAdmin III, I just don't know how they work and if they support my needs? I also thought about creating a python script, but querying my database has become pretty slow, so this seems not to be an option either.
-----------------------------------------------------
| id (serial - auto incrementing int) | - primary key
| did (varchar) |
| sensorid (int) |
| timestamp (bigint) |
| data (json) |
| db_timestamp (bigint) |
-----------------------------------------------------
If you preserved primary keys between those databases then you could create foreign tables pointing from datarestore to datastore and check what keys are missing (using for example select pk from old_table except select pk from new_table) and fetch those missing rows using the same foreign table you created. This should limit your first check for missing PK to just index only scans (+ network transfer) and then it will be index scan to fetch missing data. If you are missing only small part of it then it shouldn't take long.
If you require more detailed example then I'll update my answer.
EDIT:
Example of foreign table/server usage
Those commands need to be exuecuted on datarestore (or datastore if you choose to push data instead of pulling it).
If you don't have foreign data wrapper "installed" yet:
CREATE EXTENSION postgres_fdw;
This will create virtual server on your datarestore host. It is just some metadata pointing at foreign server:
CREATE SERVER foreign_datastore FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'foreign_hostname', dbname 'foreign_database_name',
port '5432_or_whatever_you_have_on_datastore_host');
This will tell your datarestore host what user should it connect as when using fdw on server foreign_datastore. It will be used only for your_local_role_name logged in on datarestore:
CREATE USER MAPPING FOR your_local_role_name SERVER foreign_datastore
OPTIONS (user 'foreign_username', password 'foreign_password');
You need to create schema on datarestore. It is where new foreign tables will be created.
CREATE SCHEMA schema_where_foreign_tables_will_be_created;
This will log in to remote host and create foreign tables on datarestore, pointing to tables at datastore. ONLY tables will be done this way.
No data will be copied, just structure of tables.
IMPORT FOREIGN SCHEMA foreign_datastore_schema_name_goes_here
FROM SERVER foreign_datastore INTO schema_where_foreign_tables_will_be_created;
This will return list of id that are missing in your datarestore database for this table
SELECT id FROM foreign_datastore_schema_name_goes_here.table_a
EXCEPT
SELECT id FROM datarestore_schema.table_a
You can either store them in temp table (CREATE TABLE table_a_missing_pk AS [query from above here]
Or use them right away:
INSERT INTO datarestore_schema.table_a (id, did, sensorid, timestamp, data, db_timestamp)
SELECT id, did, sensorid, timestamp, data, db_timestamp
FROM foreign_datastore_schema_name_goes_here.table_a
WHERE id = ANY((
SELECT array_agg(id)
FROM (
SELECT id FROM foreign_datastore_schema_name_goes_here.table_a
EXCEPT
SELECT id FROM datarestore_schema.table_a
) sub
)::int[])
From my tests, this should push-down (meaning send to remote host) something like that:
Remote SQL: SELECT id, did, sensorid, timestamp, data, db_timestamp
FROM foreign_datastore_schema_name_goes_here.table_a WHERE ((id = ANY ($1::integer[])))
You can make sure it does by running explain verbose on your full query to see what plan it will execute. You should see Remote SQL in there.
In case it does not work as expected, you can instead create temp table as mentioned earlier and make sure that this temp table is on datastore host.
Alternative approach would be to create foreign server on datastore pointing to datarestore and push data from your old database to new one (you can insert into foreign tables). This way you won't have to worry about list of id not being pushed down to datastore and instead fetching all data and filtering them afterwards (with would be extremely slow).

how can we identified schema name in sybase ase 15.5?

I am trying to get schema name in sybase database.
First I have create login(user1) from sa user and than i have connect with user1 by giving login name(user1) and password now i have tried to create table by giving following command:-
create table user1.table1(
emp_id int not null,
name varchar(80) not null
)
but it was showing access denied error than i have logged-in from sa user and grant sa_role to user1 and then again i have run above mention query for create table and table were created successfully.
here I am not exactly getting that user1 is schema name or not or how can I identified schema name?
I want to also know that is there any role except sa_role for grant create insert delete table ,views and all other objects of sybase database.
Sybase ASE does not use the schema concept that SQL Server and Oracle use. Objects are located inside a database, and owned by a user - no other logical separations are there. So your syntax is wrong.
create table table1
(
emp_id int not null,
name varchar(80) not null
)
Sybase ASE Create Table
Additionally, Sybase/SAP best practices tells us all database objects should be created/owned by dbo with permissions granted to groups/roles/users to access those objects. Users who own database objects can not be removed, so if User1 gets fired, you will have to identify all the objects he owns, and change the ownership of those objects before his account can be deleted.
So for your example, the dbo user (typically sa) would create the objects, then GRANT permissions (INSERT/UPDATE/DELETE/etc) to the groups/roles/users who need access.
More information on managing user permissions can be found in the Sybase ASE System Administrators Guide Vol 1.
And more information about Roles/Groups from the System Admin Guide.

How do I protect specific columns from having their values explicitly set via a REST API update?

I have multiple tables that I would like users to be able to update through the rest api, and many (if not all) have columns with sensible defaults.
The web app itself can be designed to hide these columns, but I want to allow direct access to the api as well so that others can make use of the data however they see fit.
Unfortunately, this means they can set the defaulted columns explicitly (set timestamp columns to 1972, or set id columns to arbitrary values).
What mechanisms are available to restrict this on the backend (Postgres 9.4)?
You should do this at API level.
If anybody issues a malformed request (e.g. they want to overwrite an ID or a timestamp), answer with a proper status code (perhaps 400), amended with a meaningful message, for instance "Hey you tried to update , which is read only."
If you would really insist to handle it at db level, here they suggest that:
The easiest way is to create BEFORE UPDATE trigger that will compare OLD and NEW row and RAISE EXCEPTION if the change to the row is forbidden.
I've had some luck experimenting with Postgres' column-level grants. It's important in a development environment to make sure that your database users isn't a superuser (if it is, create a second superuser, then revoke it from the dev account with alter role).
Then, commands similar to these can be run on a table:
revoke all on schema.table from dev_user;
grant select, delete, references on schema.table to dev_user;
grant update (col1, col2) on schema.table to dev_user;
grant insert (col1, col2) on schema.table to dev_user;
Some caveats:
Remember to grant "references" as well if another table will fkey to it.
Remember to give col1 and col2 (and any other) sane defaults, because the API will be unable to change those in any way.
DO NOT FORGET TO CREATE A SECOND SUPERUSER ACCOUNT BEFORE REVOKING SUPERUSER STATUS FROM THE DEV ACCOUNT. It is possible to recover this, but a big pain in the ass.
Also, if you're keeping these grant/revocations in the same file as the create table statement, the following form might be of use:
do $$begin execute 'grant select, delete, references on schema.table to ' || current_user; end$$;
This way the statements will translate correctly to production, which may not use the same username as in development.
PostgreSQL since version 9.3 supports updatable views, so instead of exposing actual table you can expose a view with a limited subset of columns:
CREATE TABLE foo (id SERIAL, name VARCHAR, protected NUMERIC DEFAULT 0);
CREATE VIEW foo_v AS SELECT name FROM foo;
Now you can do things like:
INSERT INTO foo_v VALUES ('foobar');
UPDATE foo_v SET name = 'foo' WHERE name = 'foobar';
If you need more you can use INSTEAD INSERT/UPDATE RULE or INSTEAD OF INSERT TRIGGER.

Do not have select privilege for temporary table in db2 stored procedure

I am running a stored procedure in DB2 10.1 which creates a created global temporary table and it returns the following error message that seems to say that it cannot select from the temporary table that it has just created in the same stored procedure
"USER" does not have the required authorization or privilege to
perform operation "SELECT" on object "MYSCHEMA.MYTABLE"..
SQLCODE=-551, SQLSTATE=42501, DRIVER=4.16.53
I have not encountered this problem with the other stored procedures and they create temp tables in the same way. The user privileges are controlled by groups, but due to issues with the groups I have started to give privileges to the users directly.
I cannot grant select permissions to the temp table because its not yet created and not sure how to fix this situation.
Has anyone come across this problem before and if so how did you fix it?
Thanks for any help.