Skip to content

fix for DB user drop query when granted some permission #3789

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: BABEL_5_X_DEV
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions contrib/babelfishpg_tsql/src/pl_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@
#include "table_variable_mvcc.h"

#include "access/xact.h"
#include <catalog/pg_auth_members_d.h>
#include "utils/fmgroids.h"
#include "access/genam.h"

extern int escape_hatch_set_transaction_isolation_level;
extern bool pltsql_recursive_triggers;
Expand Down Expand Up @@ -177,6 +180,7 @@ static void revoke_type_permission_from_public(PlannedStmt *pstmt, const char *q
ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc, List *type_name);
static void set_current_query_is_create_tbl_check_constraint(Node *expr);
static void validateUserAndRole(char *name);
static void shdepDropOwned_utility(List *roleoids, DropBehavior behavior);

static void bbf_ExecDropStmt(DropStmt *stmt);

Expand Down Expand Up @@ -2394,6 +2398,114 @@ validateUserAndRole(char *name)
errmsg("'%s' is not a valid name because it contains invalid characters.", name)));
}

void
shdepDropOwned_utility(List *roleids, DropBehavior behavior)
{
Relation sdepRel;
ListCell *cell;
ObjectAddresses *deleteobjs;

deleteobjs = new_object_addresses();

/*
* We don't need this strong a lock here, but we'll call routines that
* acquire RowExclusiveLock. Better get that right now to avoid potential
* deadlock failures.
*/
sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);

/*
* For each role, find the dependent objects and drop them only if
*/
foreach(cell, roleids)
{
Oid roleid = lfirst_oid(cell);
ScanKeyData key[2];
SysScanDesc scan;
HeapTuple tuple;

/* Doesn't work for pinned objects */
if (IsPinnedObject(AuthIdRelationId, roleid))
{
ObjectAddress obj;

obj.classId = AuthIdRelationId;
obj.objectId = roleid;
obj.objectSubId = 0;

ereport(ERROR,
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
errmsg("cannot drop objects owned by %s because they are "
"required by the database system",
getObjectDescription(&obj, false))));
}

ScanKeyInit(&key[0],
Anum_pg_shdepend_refclassid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(AuthIdRelationId));
ScanKeyInit(&key[1],
Anum_pg_shdepend_refobjid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(roleid));

scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
NULL, 2, key);

while ((tuple = systable_getnext(scan)) != NULL)
{
Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);

/*
* We only operate on shared objects and objects in the current
* database
*/
if (sdepForm->dbid != MyDatabaseId &&
sdepForm->dbid != InvalidOid)
continue;

if (sdepForm->deptype == SHARED_DEPENDENCY_ACL)
{

/*
* Dependencies on role grants are recorded using
* SHARED_DEPENDENCY_ACL, but unlike a regular ACL list
* which stores all permissions for a particular object in
* a single ACL array, there's a separate catalog row for
* each grant - so removing the grant just means removing
* the entire row.
*/
if (sdepForm->classid != AuthMemRelationId)
{
RemoveRoleFromObjectACL(roleid,
sdepForm->classid,
sdepForm->objid);
break;
}
/* FALLTHROUGH */

}
}

systable_endscan(scan);
}

/*
* For stability of deletion-report ordering, sort the objects into
* approximate reverse creation order before deletion. (This might also
* make the deletion go a bit faster, since there's less chance of having
* to rearrange the objects due to dependencies.)
*/
sort_object_addresses(deleteobjs);

/* the dependency mechanism does the actual work */
performMultipleDeletions(deleteobjs, behavior, 0);

table_close(sdepRel, RowExclusiveLock);

free_object_addresses(deleteobjs);
}


/*
* Use this hook to handle utility statements that needs special treatment, and
Expand Down Expand Up @@ -3824,6 +3936,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt,
Oid db_owner = get_db_owner_oid(db_name, false);
Oid db_accessadmin = get_db_accessadmin_oid(db_name, false);
Oid db_securityadmin = get_db_securityadmin_oid(db_name, false);
List *role_oids = NIL;

foreach(item, stmt->roles)
{
Expand All @@ -3837,6 +3950,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt,

user_name = get_physical_user_name(db_name, rolspec->rolename, false, true);
role_oid = get_role_oid(user_name, true);
role_oids = list_append_unique_oid(role_oids, role_oid);

if (!OidIsValid(role_oid) || /* Not found */
(drop_user && get_db_principal_kind(role_oid, db_name) != BBF_USER) || /* Found but not a user in current logical db */
Expand Down Expand Up @@ -3914,6 +4028,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt,
pfree(rolspec->rolename);

rolspec->rolename = user_name;
shdepDropOwned_utility(role_oids,DROP_CASCADE);
}
}
else
Expand Down
23 changes: 23 additions & 0 deletions test/JDBC/expected/BABEL-ROLE.out
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,29 @@ GO
DROP DATABASE db1
GO

--Drop user when user has some permissions
create database mydb
go
use mydb
go
create login u1 with password = '123'
go
create user u1
go
create table t(a int)
go
grant select on t to u1
go
drop user u1
go
drop login u1
go
drop table t
go
use master
GO
drop database mydb
GO
-- Check if catalog is cleaned up
SELECT rolname, type, orig_username, database_name
FROM sys.babelfish_authid_user_ext
Expand Down
23 changes: 23 additions & 0 deletions test/JDBC/input/BABEL-ROLE.sql
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,29 @@ GO
DROP DATABASE db1
GO

--Drop user when user has some permissions
create database mydb
go
use mydb
go
create login u1 with password = '123'
go
create user u1
go
create table t(a int)
go
grant select on t to u1
go
drop user u1
go
drop login u1
go
drop table t
go
use master
GO
drop database mydb
GO
-- Check if catalog is cleaned up
SELECT rolname, type, orig_username, database_name
FROM sys.babelfish_authid_user_ext
Expand Down
Loading