mirror of
https://github.com/postgres/postgres.git
synced 2025-06-26 12:21:12 +03:00
Use a bitmask to represent role attributes
The previous representation using a boolean column for each attribute would not scale as well as we want to add further attributes. Extra auxilliary functions are added to go along with this change, to make up for the lost convenience of access of the old representation. Catalog version bumped due to change in catalogs and the new functions. Author: Adam Brightwell, minor tweaks by Álvaro Reviewed by: Stephen Frost, Andres Freund, Álvaro Herrera
This commit is contained in:
@ -115,6 +115,7 @@ static Oid convert_type_name(text *typename);
|
||||
static AclMode convert_type_priv_string(text *priv_type_text);
|
||||
static AclMode convert_role_priv_string(text *priv_type_text);
|
||||
static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode);
|
||||
static RoleAttr convert_role_attr_string(text *attr_type_text);
|
||||
|
||||
static void RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue);
|
||||
|
||||
@ -4602,6 +4603,186 @@ pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode)
|
||||
return ACLCHECK_NO_PRIV;
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_has_role_attribute_id
|
||||
* Check that the role with the given oid has the given named role
|
||||
* attribute.
|
||||
*
|
||||
* Note: This function applies superuser checks. Therefore, if the provided
|
||||
* role is a superuser, then the result will always be true.
|
||||
*/
|
||||
Datum
|
||||
pg_has_role_attribute_id(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid roleoid = PG_GETARG_OID(0);
|
||||
text *attr_type_text = PG_GETARG_TEXT_P(1);
|
||||
RoleAttr attribute;
|
||||
|
||||
attribute = convert_role_attr_string(attr_type_text);
|
||||
|
||||
PG_RETURN_BOOL(has_role_attribute(roleoid, attribute));
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_has_role_attribute_name
|
||||
* Check that the named role has the given named role attribute.
|
||||
*
|
||||
* Note: This function applies superuser checks. Therefore, if the provided
|
||||
* role is a superuser, then the result will always be true.
|
||||
*/
|
||||
Datum
|
||||
pg_has_role_attribute_name(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Name rolename = PG_GETARG_NAME(0);
|
||||
text *attr_type_text = PG_GETARG_TEXT_P(1);
|
||||
Oid roleoid;
|
||||
RoleAttr attribute;
|
||||
|
||||
roleoid = get_role_oid(NameStr(*rolename), false);
|
||||
attribute = convert_role_attr_string(attr_type_text);
|
||||
|
||||
PG_RETURN_BOOL(has_role_attribute(roleoid, attribute));
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_check_role_attribute_id
|
||||
* Check that the role with the given oid has the given named role
|
||||
* attribute.
|
||||
*
|
||||
* Note: This function is different from 'pg_has_role_attribute_id_attr' in that
|
||||
* it does *not* apply any superuser checks. Therefore, this function will
|
||||
* always return the set value of the attribute, despite the superuser-ness of
|
||||
* the provided role.
|
||||
*/
|
||||
Datum
|
||||
pg_check_role_attribute_id(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid roleoid = PG_GETARG_OID(0);
|
||||
text *attr_type_text = PG_GETARG_TEXT_P(1);
|
||||
RoleAttr attribute;
|
||||
|
||||
attribute = convert_role_attr_string(attr_type_text);
|
||||
|
||||
PG_RETURN_BOOL(check_role_attribute(roleoid, attribute));
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_check_role_attribute_name
|
||||
* Check that the named role has the given named role attribute.
|
||||
*
|
||||
* Note: This function is different from 'pg_has_role_attribute_name_attr' in
|
||||
* that it does *not* apply any superuser checks. Therefore, this function will
|
||||
* always return the set value of the attribute, despite the superuser-ness of
|
||||
* the provided role.
|
||||
*/
|
||||
Datum
|
||||
pg_check_role_attribute_name(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Name rolename = PG_GETARG_NAME(0);
|
||||
text *attr_type_text = PG_GETARG_TEXT_P(1);
|
||||
Oid roleoid;
|
||||
RoleAttr attribute;
|
||||
|
||||
roleoid = get_role_oid(NameStr(*rolename), false);
|
||||
attribute = convert_role_attr_string(attr_type_text);
|
||||
|
||||
PG_RETURN_BOOL(check_role_attribute(roleoid, attribute));
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_check_role_attribute_attrs
|
||||
* Check that the named attribute is enabled in the given RoleAttr
|
||||
* representation of role attributes.
|
||||
*/
|
||||
Datum
|
||||
pg_check_role_attribute_attrs(PG_FUNCTION_ARGS)
|
||||
{
|
||||
RoleAttr attributes = PG_GETARG_INT64(0);
|
||||
text *attr_type_text = PG_GETARG_TEXT_P(1);
|
||||
RoleAttr attribute;
|
||||
|
||||
attribute = convert_role_attr_string(attr_type_text);
|
||||
|
||||
PG_RETURN_BOOL(attributes & attribute);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_all_role_attributes
|
||||
* Convert a RoleAttr representation of role attributes into an array of
|
||||
* corresponding text values.
|
||||
*
|
||||
* The first and only argument is a RoleAttr (int64) representation of the
|
||||
* role attributes.
|
||||
*/
|
||||
Datum
|
||||
pg_all_role_attributes(PG_FUNCTION_ARGS)
|
||||
{
|
||||
RoleAttr attributes = PG_GETARG_INT64(0);
|
||||
Datum *temp_array;
|
||||
ArrayType *result;
|
||||
int i = 0;
|
||||
|
||||
/*
|
||||
* Short-circuit the case for no attributes assigned.
|
||||
*/
|
||||
if (attributes == ROLE_ATTR_NONE)
|
||||
PG_RETURN_ARRAYTYPE_P(construct_empty_array(TEXTOID));
|
||||
|
||||
temp_array = (Datum *) palloc(N_ROLE_ATTRIBUTES * sizeof(Datum));
|
||||
|
||||
/* Determine which attributes are assigned. */
|
||||
if (attributes & ROLE_ATTR_SUPERUSER)
|
||||
temp_array[i++] = CStringGetTextDatum(_("Superuser"));
|
||||
if (attributes & ROLE_ATTR_INHERIT)
|
||||
temp_array[i++] = CStringGetTextDatum(_("Inherit"));
|
||||
if (attributes & ROLE_ATTR_CREATEROLE)
|
||||
temp_array[i++] = CStringGetTextDatum(_("Create Role"));
|
||||
if (attributes & ROLE_ATTR_CREATEDB)
|
||||
temp_array[i++] = CStringGetTextDatum(_("Create DB"));
|
||||
if (attributes & ROLE_ATTR_CATUPDATE)
|
||||
temp_array[i++] = CStringGetTextDatum(_("Catalog Update"));
|
||||
if (attributes & ROLE_ATTR_CANLOGIN)
|
||||
temp_array[i++] = CStringGetTextDatum(_("Login"));
|
||||
if (attributes & ROLE_ATTR_REPLICATION)
|
||||
temp_array[i++] = CStringGetTextDatum(_("Replication"));
|
||||
if (attributes & ROLE_ATTR_BYPASSRLS)
|
||||
temp_array[i++] = CStringGetTextDatum(_("Bypass RLS"));
|
||||
|
||||
result = construct_array(temp_array, i, TEXTOID, -1, false, 'i');
|
||||
|
||||
PG_RETURN_ARRAYTYPE_P(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* convert_role_attr_string
|
||||
* Convert text string to RoleAttr value.
|
||||
*/
|
||||
static RoleAttr
|
||||
convert_role_attr_string(text *attr_type_text)
|
||||
{
|
||||
char *attr_type = text_to_cstring(attr_type_text);
|
||||
|
||||
if (pg_strcasecmp(attr_type, "SUPERUSER") == 0)
|
||||
return ROLE_ATTR_SUPERUSER;
|
||||
else if (pg_strcasecmp(attr_type, "INHERIT") == 0)
|
||||
return ROLE_ATTR_INHERIT;
|
||||
else if (pg_strcasecmp(attr_type, "CREATEROLE") == 0)
|
||||
return ROLE_ATTR_CREATEROLE;
|
||||
else if (pg_strcasecmp(attr_type, "CREATEDB") == 0)
|
||||
return ROLE_ATTR_CREATEDB;
|
||||
else if (pg_strcasecmp(attr_type, "CATUPDATE") == 0)
|
||||
return ROLE_ATTR_CATUPDATE;
|
||||
else if (pg_strcasecmp(attr_type, "CANLOGIN") == 0)
|
||||
return ROLE_ATTR_CANLOGIN;
|
||||
else if (pg_strcasecmp(attr_type, "REPLICATION") == 0)
|
||||
return ROLE_ATTR_REPLICATION;
|
||||
else if (pg_strcasecmp(attr_type, "BYPASSRLS") == 0)
|
||||
return ROLE_ATTR_BYPASSRLS;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("unrecognized role attribute: \"%s\"", attr_type)));
|
||||
}
|
||||
|
||||
/*
|
||||
* initialization function (called by InitPostgres)
|
||||
@ -4634,23 +4815,6 @@ RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
|
||||
}
|
||||
|
||||
|
||||
/* Check if specified role has rolinherit set */
|
||||
static bool
|
||||
has_rolinherit(Oid roleid)
|
||||
{
|
||||
bool result = false;
|
||||
HeapTuple utup;
|
||||
|
||||
utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
|
||||
if (HeapTupleIsValid(utup))
|
||||
{
|
||||
result = ((Form_pg_authid) GETSTRUCT(utup))->rolinherit;
|
||||
ReleaseSysCache(utup);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get a list of roles that the specified roleid has the privileges of
|
||||
*
|
||||
@ -4697,7 +4861,7 @@ roles_has_privs_of(Oid roleid)
|
||||
int i;
|
||||
|
||||
/* Ignore non-inheriting roles */
|
||||
if (!has_rolinherit(memberid))
|
||||
if (!has_role_attribute(memberid, ROLE_ATTR_INHERIT))
|
||||
continue;
|
||||
|
||||
/* Find roles that memberid is directly a member of */
|
||||
|
Reference in New Issue
Block a user