如果要授予或回收角色的成员关系,可以使用SQL命令“GRANT/REVOKE”。如果声明了“WITH ADMIN OPTION”选项,那么被加入的成员角色还可以将其他角色加入到父角色中。角色的授予或回收通过调用GrantRole函数来实现,该函数只有一个类型为GrantRoleStmt结构的参数。相关代码如下:
typedef struct GrantRoleStmt {
NodeTag type;
List* granted_roles;/* 被授予或回收的角色集合 */
List* grantee_roles;/* 从granted_roles中增加或删除的角色集合 */
Bool is_grant;/* true代表授权,false代表回收 */
Bool admin_opt;/* 是否带有with admin option选项 */
char* grantor;/* 授权者 */
Drop Behaviorbehavior;/* 是否级联回收角色 */
} GrantRoleStmt;
授予角色时,grantee_roles中的角色将被添加到granted_roles,通过调用函数AddRoleMems实现;回收角色时,将grantee_roles中的角色从granted_roles中删除,通过调用函数DelRoleMems实现。
函数AddRoleMems的实现流程如图9-17所示。
图9-17 openGauss增加用户成员流程图
函数AddRoleMems的具体实现代码如下,其中:
(1) rolename和roleid分别表示要被加入成员的角色的名称和OID。
(2) memberNames和memberIds分别是要添加的角色名称和OID的列表。
(3) grantorId表示授权者的OID。
(4) admin_opt表示是否带有with admin option选项。
static void AddRoleMems(
const char* rolename, Oid roleid, const List* memberNames, List* memberIds, Oid grantorId, bool admin_opt)
{
. . .
/* 校验执行者的权限 */
if (superuser_arg(roleid)) {
if (!isRelSuperuser())
ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Permission denied.")));
. . .
}
. . .
if (grantorId != GetUserId() && !superuser())
ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be system admin to set grantor")));
/* 循环处理要添加的角色 */
pg_authmem_rel = heap_open(AuthMemRelationId, RowExclusiveLock);
pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
forboth(nameitem, memberNames, iditem, memberIds)
{
/* 针对角色和成员信息创建pg_auth_members元组,再将新元组插入到系统表中 */
. . .
new_record[Anum_pg_auth_members_roleid - 1] = ObjectIdGetDatum(roleid);
new_record[Anum_pg_auth_members_member -1] = ObjectIdGetDatum(memberid);
new_record[Anum_pg_auth_members_grantor - 1] = ObjectIdGetDatum(grantorId);
new_record[Anum_pg_auth_members_admin_option - 1] = BoolGetDatum(admin_opt);
if (HeapTupleIsValid(authmem_tuple)) {
new_record_repl[Anum_pg_auth_members_grantor - 1] = true;
new_record_repl[Anum_pg_auth_members_admin_option - 1] = true;
tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc, new_record, new_record_nulls, new_record_repl);
simple_heap_update(pg_authmem_rel, &tuple->t_self, tuple);
CatalogUpdateIndexes(pg_authmem_rel, tuple);
ReleaseSysCache(authmem_tuple);
} else {
tuple = heap_form_tuple(pg_authmem_dsc, new_record, new_record_nulls);
(void)simple_heap_insert(pg_authmem_rel, tuple);
CatalogUpdateIndexes(pg_authmem_rel, tuple);
}
}
. . .
heap_close(pg_authmem_rel, NoLock);
}
函数DelRoleMems的实现过程类似。首先对执行者的相关权限进行校验,然后循环处理要删除的角色,删除系统表pg_auth_member中相关的元组。