diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2015-03-09 15:41:54 -0300 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2015-03-09 15:41:54 -0300 |
commit | 31eae6028eca4365e7165f5f33fee1ed0486aee0 (patch) | |
tree | 388807d83f4aecda050e5f98f880752fbe773b16 /src/backend/utils/adt/acl.c | |
parent | fa83f809458a966dff225d3d266399d48e7b5e6e (diff) | |
download | postgresql-31eae6028eca4365e7165f5f33fee1ed0486aee0.tar.gz postgresql-31eae6028eca4365e7165f5f33fee1ed0486aee0.zip |
Allow CURRENT/SESSION_USER to be used in certain commands
Commands such as ALTER USER, ALTER GROUP, ALTER ROLE, GRANT, and the
various ALTER OBJECT / OWNER TO, as well as ad-hoc clauses related to
roles such as the AUTHORIZATION clause of CREATE SCHEMA, the FOR clause
of CREATE USER MAPPING, and the FOR ROLE clause of ALTER DEFAULT
PRIVILEGES can now take the keywords CURRENT_USER and SESSION_USER as
user specifiers in place of an explicit user name.
This commit also fixes some quite ugly handling of special standards-
mandated syntax in CREATE USER MAPPING, which in particular would fail
to work in presence of a role named "current_user".
The special role specifiers PUBLIC and NONE also have more consistent
handling now.
Also take the opportunity to add location tracking to user specifiers.
Authors: Kyotaro Horiguchi. Heavily reworked by Álvaro Herrera.
Reviewed by: Rushabh Lathia, Adam Brightwell, Marti Raudsepp.
Diffstat (limited to 'src/backend/utils/adt/acl.c')
-rw-r--r-- | src/backend/utils/adt/acl.c | 116 |
1 files changed, 115 insertions, 1 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 411d779be6b..7701fc5ac07 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -5105,7 +5105,7 @@ select_best_grantor(Oid roleId, AclMode privileges, /* * get_role_oid - Given a role name, look up the role's OID. * - * If missing_ok is false, throw an error if tablespace name not found. If + * If missing_ok is false, throw an error if role name not found. If * true, just return InvalidOid. */ Oid @@ -5133,3 +5133,117 @@ get_role_oid_or_public(const char *rolname) return get_role_oid(rolname, false); } + +/* + * Given a RoleSpec node, return the OID it corresponds to. If missing_ok is + * true, return InvalidOid if the role does not exist. + * + * PUBLIC is always disallowed here. Routines wanting to handle the PUBLIC + * case must check the case separately. + */ +Oid +get_rolespec_oid(const Node *node, bool missing_ok) +{ + RoleSpec *role; + Oid oid; + + if (!IsA(node, RoleSpec)) + elog(ERROR, "invalid node type %d", node->type); + + role = (RoleSpec *) node; + switch (role->roletype) + { + case ROLESPEC_CSTRING: + Assert(role->rolename); + oid = get_role_oid(role->rolename, missing_ok); + break; + + case ROLESPEC_CURRENT_USER: + oid = GetUserId(); + break; + + case ROLESPEC_SESSION_USER: + oid = GetSessionUserId(); + break; + + case ROLESPEC_PUBLIC: + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("role \"%s\" does not exist", "public"))); + oid = InvalidOid; /* make compiler happy */ + break; + + default: + elog(ERROR, "unexpected role type %d", role->roletype); + } + + return oid; +} + +/* + * Given a RoleSpec node, return the pg_authid HeapTuple it corresponds to. + * Caller must ReleaseSysCache when done with the result tuple. + */ +HeapTuple +get_rolespec_tuple(const Node *node) +{ + RoleSpec *role; + HeapTuple tuple; + + role = (RoleSpec *) node; + if (!IsA(node, RoleSpec)) + elog(ERROR, "invalid node type %d", node->type); + + switch (role->roletype) + { + case ROLESPEC_CSTRING: + Assert(role->rolename); + tuple = SearchSysCache1(AUTHNAME, CStringGetDatum(role->rolename)); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("role \"%s\" does not exist", role->rolename))); + break; + + case ROLESPEC_CURRENT_USER: + tuple = SearchSysCache1(AUTHOID, GetUserId()); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for role %u", GetUserId()); + break; + + case ROLESPEC_SESSION_USER: + tuple = SearchSysCache1(AUTHOID, GetSessionUserId()); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for role %u", GetSessionUserId()); + break; + + case ROLESPEC_PUBLIC: + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("role \"%s\" does not exist", "public"))); + tuple = NULL; /* make compiler happy */ + + default: + elog(ERROR, "unexpected role type %d", role->roletype); + } + + return tuple; +} + +/* + * Given a RoleSpec, returns a palloc'ed copy of the corresponding role's name. + */ +char * +get_rolespec_name(const Node *node) +{ + HeapTuple tp; + Form_pg_authid authForm; + char *rolename; + + tp = get_rolespec_tuple(node); + authForm = (Form_pg_authid) GETSTRUCT(tp); + rolename = pstrdup(NameStr(authForm->rolname)); + ReleaseSysCache(tp); + + return rolename; +} |