record_role_dependency.patch
application/octet-stream
Filename: record_role_dependency.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/commands/user.c | 53 | 1 |
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index e7ade898a4..3b7b49b86a 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -131,7 +131,8 @@ have_createrole_privilege(void)
Oid
CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
{
- Relation pg_authid_rel;
+ Relation pg_authid_rel,
+ pg_auth_members_rel;
TupleDesc pg_authid_dsc;
HeapTuple tuple;
Datum new_record[Natts_pg_authid] = {0};
@@ -543,6 +544,11 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
GrantRoleOptions poptself;
List *memberSpecs;
List *memberIds = list_make1_oid(currentUserId);
+ ScanKeyData scankey;
+ SysScanDesc sscan;
+ HeapTuple tmp_tuple;
+ ObjectAddress depobj;
+ ObjectAddress refobj;
current_role->roletype = ROLESPEC_CURRENT_ROLE;
current_role->location = -1;
@@ -565,6 +571,49 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
*/
CommandCounterIncrement();
+ /*
+ * Register the dependency of the current user's members on the current
+ * user.
+ *
+ * This is only done for members who have the admin option. The reason
+ * is that if the current user is dropped, members with the admin option
+ * would lose their control over the newly created role. Without this
+ * dependency, only superusers would be able to manage the new role, as
+ * the admin option would be revoked from these members.
+ */
+ pg_auth_members_rel = table_open(AuthMemRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&scankey,
+ Anum_pg_auth_members_roleid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(GetUserId()));
+
+ sscan = systable_beginscan(pg_auth_members_rel, AuthMemRoleMemIndexId,
+ true, NULL, 1, &scankey);
+
+ while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
+ {
+ Form_pg_auth_members authmem_form;
+ authmem_form = (Form_pg_auth_members) GETSTRUCT(tmp_tuple);
+
+ if (authmem_form->admin_option)
+ {
+ depobj.classId = AuthIdRelationId;
+ depobj.objectId = authmem_form->member;
+ depobj.objectSubId = 0;
+
+ refobj.classId = AuthIdRelationId;
+ refobj.objectId = authmem_form->roleid;
+ refobj.objectSubId = 0;
+
+ recordSharedDependencyOn(&depobj, &refobj,
+ SHARED_DEPENDENCY_ACL);
+ }
+ }
+
+ systable_endscan(sscan);
+ table_close(pg_auth_members_rel, NoLock);
+
/*
* Because of the implicit grant above, a CREATEROLE user who creates
* a role has the ability to grant that role back to themselves with
@@ -1301,6 +1350,9 @@ DropRole(DropRoleStmt *stmt)
errdetail_internal("%s", detail),
errdetail_log("%s", detail_log)));
+ /* Remove any shared depencies of this role. */
+ deleteSharedDependencyRecordsFor(AuthIdRelationId, roleid, 0);
+
/*
* Remove the role from the pg_authid table
*/