Trigger to grant permission to newly created procedure on the fly - stored-procedures

The application I am using creates procedures when certain activities are performed on the UI.
I want to grant debug permission when those store procs are created so that users who belong to certain DB roles can view the code for that stored proc.
Can this be done using a trigger? I tried to use a DDL trigger on create, while it works for printing a dbms_output.put_line value, when i use an execute immediate "GRANT DEBUG "|| procname || " TO ROLE", it complains.
Is there a way I can achieve this more elegantly?

Related

Firebase Realtime Database update multiple children without a common parent

Let's say I want to update /groups/$groupID and users/$userID in the single update call. The update should fail if any of the update calls fail. I'm getting
Listener at / failed: permission_denied
when trying to update via
ref().update({
'groups/...': 'value1',
'users/...': 'value2'
})
probably because I have no rules defined at the root / level, but separately in each child (separately in /groups, /users, etc.).
If I would, indeed, define a write rule at the root level, wouldn't that mean that all the child write rules are overridden by it? I wouldn't want that to happen. I've looked into transaction API and it seems that the transactions are ran 'on a reference', which in this case would also be the root reference.
Is there a different way of running a transaction that runs multiple updates?

MariaDB: Executing stored procedure, Select denied, privilege via role

I have created a stored procedure with a user db_owner (Definer = db_owner, SQL Security Definer). This procedure selects some data from a table. The db_owner has full select privilege on all tables of his database via a role. Executing the procedure works fine, also selects from this table.
Another user db_connect has execute privilege for the procedure, executing procedure works also fine, but I get an error "ERROR 1142 (42000): SELECT command denied to user db_owner'#'host' for table 'xxx'"
If I grant a privilege to the user db_owner (grant select on db.'xxx' to db_owner#'host') without using the role, it works. Have anyone a better idea? I want to use roles.
MariaDB 10.3

How to disable session maintenance when creating a user with Authlogic

When a user is created, Authlogic sets a persistence token which it uses for session maintenance. As part of this process, it does a query like:
User Exists (517.6ms) SELECT 1 AS one FROM 'users' WHERE 'users'.'persistence_token' = BINARY 'xyz123123' AND 'users'.'deleted_at' IS NULL LIMIT 1
which as you can see is pretty expensive on our database. This code is evidenced here: https://github.com/binarylogic/authlogic/blob/4f03d6520d8b13394023f5cbc9ba74ab1464b89d/lib/authlogic/session/session.rb
This is particularly problematic with our user sync function which creates thousands of users and thus this query is very very expensive.
How can we disable this behavior during this operation and set it later? I tried to use user.save_without_session_maintenance but that didn’t seem to work for me.

Execute stored proc fails with GRANT EXECUTE because of table permissions

I have created a stored proc on schema X that does a select across 10+ tables that are in schema X and Y.
I created a database role DBRole and added a new AD Group Login to it.
I thought all I needed to do was grant execute on x.MyStoredProc to DBRole,
but I'm getting errors because of select permission..
Stored Procedure MYSCHEMA.MyStoredProc failed: The SELECT permission
was denied on the object 'myTable', database 'Db', schema 'dbo'.
I wondered if it was because the tables its failing on are in a different schema but, doing a quick test that still worked..
Can anyone explain what I'm missing?

Identifying a connection ID in Postgres

I have a Postgres database (9) that I am writing a trigger for. I want the trigger to set the modification time, and user id for a record. In Firebird you have a CONNECTIONID that you can use in a trigger, so you could add a value to a table when you connect to the database (this is a desktop application, so connections are persistent for the lifetime of the app), something like this:
UserId | ConnectionId
---------------------
544 | 3775
and then look up in the trigger that connectionid 3775 belongs to userid 544 and use 544 as the user that modified the record.
Is there anything similar I can use in Postgres?
you could use the process id. It can be retrieved with:
pg_backend_pid()
With this pid you can also use the table pg_stat_activity to get more information about the current backend, althouht you already should know everything, since you are using this backend.
Or better. Just create a serial, and retrieve one value from it for each connection:
CREATE SEQUENCE 'connectionids';
And then:
SELECT next_val('connectionids');
in each connection, to retrieve a connection unique id.
One way is to use the custom_variable_classes configuration option. It appears to be designed to allow the configuration of add-on modules, but can also be used to store arbitrary values in the current database session.
Something along the lines of the following needs to be added to postgresql.conf:
custom_variable_classes = 'local'
When you first connect to the database you can store whatever information you require in the custom class, like so:
SET local.userid = 'foobar';
And later in on you can retrieve this value with the current_setting() function:
SELECT current_setting('local.userid');
Adding an entry to a log table might look something like this:
INSERT INTO audit_log VALUES (now(), current_setting('local.userid'), ...)
While it may work for your desktop use case, note that process ID numbers do rollover (32768 is a common upper limit), so using them as a unique key to identify a user can run into problems. If you ever end up with leftover data from a previous session in the table that's tracking user->process mapping, that can collide with newer connections assigned the same process id once it's rolled over. It may be sufficient for your app to just make sure you aggressively clean out old mapping entries, perhaps at startup time given how you've described its operation.
To avoid this problem in general, you need to make a connection key that includes an additional bit of information, such as when the session started:
SELECT procpid,backend_start FROM pg_stat_activity WHERE procpid=pg_backend_pid();
That has to iterate over all of the connections active at the time to compute, so it does add a bit of overhead. It's possible to execute that a bit more efficiently starting in PostgreSQL 8.4:
SELECT procpid,backend_start FROM pg_stat_get_activity(pg_backend_pid());
But that only really matters if you have a large number of connections active at once.
Use current_user if you need the database user (I'm not sure that's what you want by reading your question).

Resources