提交 f9fd1764 编写于 作者: T Tom Lane

Add pg_has_role() family of privilege inquiry functions modeled after the

existing ones for object privileges.  Update the information_schema for
roles --- pg_has_role() makes this a whole lot easier, removing the need
for most of the explicit joins with pg_user.  The views should be a tad
faster now, too.  Stephen Frost and Tom Lane.
上级 e5d6b912
<!--
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.270 2005/07/25 22:12:30 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.271 2005/07/26 00:04:17 tgl Exp $
PostgreSQL documentation
-->
......@@ -8427,6 +8427,21 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, ..
<entry><type>boolean</type></entry>
<entry>does current user have privilege for language</entry>
</row>
<row>
<entry><literal><function>pg_has_role</function>(<parameter>user</parameter>,
<parameter>role</parameter>,
<parameter>privilege</parameter>)</literal>
</entry>
<entry><type>boolean</type></entry>
<entry>does user have privilege for role</entry>
</row>
<row>
<entry><literal><function>pg_has_role</function>(<parameter>role</parameter>,
<parameter>privilege</parameter>)</literal>
</entry>
<entry><type>boolean</type></entry>
<entry>does current user have privilege for role</entry>
</row>
<row>
<entry><literal><function>has_schema_privilege</function>(<parameter>user</parameter>,
<parameter>schema</parameter>,
......@@ -8473,6 +8488,9 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, ..
<indexterm zone="functions-info">
<primary>has_language_privilege</primary>
</indexterm>
<indexterm zone="functions-info">
<primary>pg_has_role</primary>
</indexterm>
<indexterm zone="functions-info">
<primary>has_schema_privilege</primary>
</indexterm>
......@@ -8536,6 +8554,14 @@ SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute');
<literal>USAGE</literal>.
</para>
<para>
<function>pg_has_role</function> checks whether a user
can access a role in a particular way. The possibilities for its
arguments are analogous to <function>has_table_privilege</function>.
The desired access privilege type must evaluate to
<literal>MEMBER</literal>.
</para>
<para>
<function>has_schema_privilege</function> checks whether a user
can access a schema in a particular way. The possibilities for its
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.120 2005/07/21 04:41:42 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.121 2005/07/26 00:04:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -75,6 +75,8 @@ static Oid convert_schema_name(text *schemaname);
static AclMode convert_schema_priv_string(text *priv_type_text);
static Oid convert_tablespace_name(text *tablespacename);
static AclMode convert_tablespace_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 void RoleMembershipCacheCallback(Datum arg, Oid relid);
......@@ -2493,6 +2495,216 @@ convert_tablespace_priv_string(text *priv_type_text)
return ACL_NO_RIGHTS; /* keep compiler quiet */
}
/*
* pg_has_role variants
* These are all named "pg_has_role" at the SQL level.
* They take various combinations of role name, role OID,
* user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
*/
/*
* pg_has_role_name_name
* Check user privileges on a role given
* name username, name rolename, and text priv name.
*/
Datum
pg_has_role_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
Name rolename = PG_GETARG_NAME(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid roleid;
Oid roleoid;
AclMode mode;
AclResult aclresult;
roleid = get_roleid_checked(NameStr(*username));
roleoid = get_roleid_checked(NameStr(*rolename));
mode = convert_role_priv_string(priv_type_text);
aclresult = pg_role_aclcheck(roleoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
* pg_has_role_name
* Check user privileges on a role given
* name rolename and text priv name.
* current_user is assumed
*/
Datum
pg_has_role_name(PG_FUNCTION_ARGS)
{
Name rolename = PG_GETARG_NAME(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
Oid roleid;
Oid roleoid;
AclMode mode;
AclResult aclresult;
roleid = GetUserId();
roleoid = get_roleid_checked(NameStr(*rolename));
mode = convert_role_priv_string(priv_type_text);
aclresult = pg_role_aclcheck(roleoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
* pg_has_role_name_id
* Check user privileges on a role given
* name usename, role oid, and text priv name.
*/
Datum
pg_has_role_name_id(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
Oid roleoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid roleid;
AclMode mode;
AclResult aclresult;
roleid = get_roleid_checked(NameStr(*username));
mode = convert_role_priv_string(priv_type_text);
aclresult = pg_role_aclcheck(roleoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
* pg_has_role_id
* Check user privileges on a role given
* role oid, and text priv name.
* current_user is assumed
*/
Datum
pg_has_role_id(PG_FUNCTION_ARGS)
{
Oid roleoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
Oid roleid;
AclMode mode;
AclResult aclresult;
roleid = GetUserId();
mode = convert_role_priv_string(priv_type_text);
aclresult = pg_role_aclcheck(roleoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
* pg_has_role_id_name
* Check user privileges on a role given
* roleid, name rolename, and text priv name.
*/
Datum
pg_has_role_id_name(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
Name rolename = PG_GETARG_NAME(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid roleoid;
AclMode mode;
AclResult aclresult;
roleoid = get_roleid_checked(NameStr(*rolename));
mode = convert_role_priv_string(priv_type_text);
aclresult = pg_role_aclcheck(roleoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
* pg_has_role_id_id
* Check user privileges on a role given
* roleid, role oid, and text priv name.
*/
Datum
pg_has_role_id_id(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
Oid roleoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
AclResult aclresult;
mode = convert_role_priv_string(priv_type_text);
aclresult = pg_role_aclcheck(roleoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
* Support routines for pg_has_role family.
*/
/*
* convert_role_priv_string
* Convert text string to AclMode value.
*
* There is only one interesting option, MEMBER, which we represent by
* ACL_USAGE since no formal ACL bit is defined for it. This convention
* is shared only with pg_role_aclcheck, below.
*/
static AclMode
convert_role_priv_string(text *priv_type_text)
{
char *priv_type;
priv_type = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(priv_type_text)));
/*
* Return mode from priv_type string
*/
if (pg_strcasecmp(priv_type, "MEMBER") == 0)
return ACL_USAGE;
if (pg_strcasecmp(priv_type, "MEMBER WITH GRANT OPTION") == 0)
return ACL_GRANT_OPTION_FOR(ACL_USAGE);
if (pg_strcasecmp(priv_type, "MEMBER WITH ADMIN OPTION") == 0)
return ACL_GRANT_OPTION_FOR(ACL_USAGE);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unrecognized privilege type: \"%s\"", priv_type)));
return ACL_NO_RIGHTS; /* keep compiler quiet */
}
/*
* pg_role_aclcheck
* Quick-and-dirty support for pg_has_role
*/
static AclResult
pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode)
{
if (mode & ACL_GRANT_OPTION_FOR(ACL_USAGE))
{
if (is_admin_of_role(roleid, role_oid))
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
else
{
if (is_member_of_role(roleid, role_oid))
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
}
/*
* initialization function (called by InitPostgres)
*/
......@@ -2637,6 +2849,14 @@ is_admin_of_role(Oid member, Oid role)
List *roles_list;
ListCell *l;
/* Fast path for simple case */
if (member == role)
return true;
/* Superusers have every privilege, so are part of every role */
if (superuser_arg(member))
return true;
/*
* Find all the roles that member is a member of,
* including multi-level recursion. We build a list in the same way
......
......@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.290 2005/07/20 17:24:39 momjian Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.291 2005/07/26 00:04:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200507201
#define CATALOG_VERSION_NO 200507251
#endif
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.377 2005/07/20 16:42:31 momjian Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.378 2005/07/26 00:04:19 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
......@@ -3240,6 +3240,19 @@ DESCR("current user privilege on tablespace by tablespace name");
DATA(insert OID = 2395 ( has_tablespace_privilege PGNSP PGUID 12 f f t f s 2 16 "26 25" _null_ _null_ _null_ has_tablespace_privilege_id - _null_ ));
DESCR("current user privilege on tablespace by tablespace oid");
DATA(insert OID = 2705 ( pg_has_role PGNSP PGUID 12 f f t f s 3 16 "19 19 25" _null_ _null_ _null_ pg_has_role_name_name - _null_ ));
DESCR("user privilege on role by username, role name");
DATA(insert OID = 2706 ( pg_has_role PGNSP PGUID 12 f f t f s 3 16 "19 26 25" _null_ _null_ _null_ pg_has_role_name_id - _null_ ));
DESCR("user privilege on role by username, role oid");
DATA(insert OID = 2707 ( pg_has_role PGNSP PGUID 12 f f t f s 3 16 "26 19 25" _null_ _null_ _null_ pg_has_role_id_name - _null_ ));
DESCR("user privilege on role by user oid, role name");
DATA(insert OID = 2708 ( pg_has_role PGNSP PGUID 12 f f t f s 3 16 "26 26 25" _null_ _null_ _null_ pg_has_role_id_id - _null_ ));
DESCR("user privilege on role by user oid, role oid");
DATA(insert OID = 2709 ( pg_has_role PGNSP PGUID 12 f f t f s 2 16 "19 25" _null_ _null_ _null_ pg_has_role_name - _null_ ));
DESCR("current user privilege on role by role name");
DATA(insert OID = 2710 ( pg_has_role PGNSP PGUID 12 f f t f s 2 16 "26 25" _null_ _null_ _null_ pg_has_role_id - _null_ ));
DESCR("current user privilege on role by role oid");
DATA(insert OID = 2290 ( record_in PGNSP PGUID 12 f f t f v 3 2249 "2275 26 23" _null_ _null_ _null_ record_in - _null_ ));
DESCR("I/O");
DATA(insert OID = 2291 ( record_out PGNSP PGUID 12 f f t f v 1 2275 "2249" _null_ _null_ _null_ record_out - _null_ ));
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.260 2005/07/10 04:54:32 momjian Exp $
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.261 2005/07/26 00:04:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -58,6 +58,12 @@ extern Datum has_tablespace_privilege_id_name(PG_FUNCTION_ARGS);
extern Datum has_tablespace_privilege_id_id(PG_FUNCTION_ARGS);
extern Datum has_tablespace_privilege_name(PG_FUNCTION_ARGS);
extern Datum has_tablespace_privilege_id(PG_FUNCTION_ARGS);
extern Datum pg_has_role_name_name(PG_FUNCTION_ARGS);
extern Datum pg_has_role_name_id(PG_FUNCTION_ARGS);
extern Datum pg_has_role_id_name(PG_FUNCTION_ARGS);
extern Datum pg_has_role_id_id(PG_FUNCTION_ARGS);
extern Datum pg_has_role_name(PG_FUNCTION_ARGS);
extern Datum pg_has_role_id(PG_FUNCTION_ARGS);
/* bool.c */
extern Datum boolin(PG_FUNCTION_ARGS);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册