aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/acl.c
diff options
context:
space:
mode:
authorJoe Conway <mail@joeconway.com>2009-08-03 21:11:40 +0000
committerJoe Conway <mail@joeconway.com>2009-08-03 21:11:40 +0000
commitbe6bca23b34b6e59f1deed1d6b44bb434dbe890e (patch)
tree23744d8f741e70d1ac47b4ba743346e53580b30d /src/backend/utils/adt/acl.c
parent7ffb14f9dbdbf0b735f9cb3b167fc848f3bd09ac (diff)
downloadpostgresql-be6bca23b34b6e59f1deed1d6b44bb434dbe890e.tar.gz
postgresql-be6bca23b34b6e59f1deed1d6b44bb434dbe890e.zip
Implement has_sequence_privilege()
Add family of functions that did not exist earlier, mainly due to historical omission. Original patch by Abhijit Menon-Sen, with review and modifications by Joe Conway. catversion.h bumped.
Diffstat (limited to 'src/backend/utils/adt/acl.c')
-rw-r--r--src/backend/utils/adt/acl.c214
1 files changed, 213 insertions, 1 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 67c4ea36e36..83d93ad3483 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.148 2009/06/11 14:49:03 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.149 2009/08/03 21:11:39 joe Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,6 +20,7 @@
#include "catalog/pg_authid.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_type.h"
+#include "catalog/pg_class.h"
#include "commands/dbcommands.h"
#include "commands/tablespace.h"
#include "foreign/foreign.h"
@@ -88,6 +89,7 @@ static AclMode convert_any_priv_string(text *priv_type_text,
static Oid convert_table_name(text *tablename);
static AclMode convert_table_priv_string(text *priv_type_text);
+static AclMode convert_sequence_priv_string(text *priv_type_text);
static AttrNumber convert_column_name(Oid tableoid, text *column);
static AclMode convert_column_priv_string(text *priv_type_text);
static Oid convert_database_name(text *databasename);
@@ -1704,6 +1706,216 @@ convert_table_priv_string(text *priv_type_text)
return convert_any_priv_string(priv_type_text, table_priv_map);
}
+/*
+ * has_sequence_privilege variants
+ * These are all named "has_sequence_privilege" at the SQL level.
+ * They take various combinations of relation name, relation 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. The variants that take a relation OID
+ * return NULL if the OID doesn't exist.
+ */
+
+/*
+ * has_sequence_privilege_name_name
+ * Check user privileges on a sequence given
+ * name username, text sequencename, and text priv name.
+ */
+Datum
+has_sequence_privilege_name_name(PG_FUNCTION_ARGS)
+{
+ Name rolename = PG_GETARG_NAME(0);
+ text *sequencename = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid roleid;
+ Oid sequenceoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = get_roleid_checked(NameStr(*rolename));
+ mode = convert_sequence_priv_string(priv_type_text);
+ sequenceoid = convert_table_name(sequencename);
+ if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ text_to_cstring(sequencename))));
+
+ aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_sequence_privilege_name
+ * Check user privileges on a sequence given
+ * text sequencename and text priv name.
+ * current_user is assumed
+ */
+Datum
+has_sequence_privilege_name(PG_FUNCTION_ARGS)
+{
+ text *sequencename = PG_GETARG_TEXT_P(0);
+ text *priv_type_text = PG_GETARG_TEXT_P(1);
+ Oid roleid;
+ Oid sequenceoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = GetUserId();
+ mode = convert_sequence_priv_string(priv_type_text);
+ sequenceoid = convert_table_name(sequencename);
+ if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ text_to_cstring(sequencename))));
+
+ aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_sequence_privilege_name_id
+ * Check user privileges on a sequence given
+ * name usename, sequence oid, and text priv name.
+ */
+Datum
+has_sequence_privilege_name_id(PG_FUNCTION_ARGS)
+{
+ Name username = PG_GETARG_NAME(0);
+ Oid sequenceoid = PG_GETARG_OID(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid roleid;
+ AclMode mode;
+ AclResult aclresult;
+ char relkind;
+
+ roleid = get_roleid_checked(NameStr(*username));
+ mode = convert_sequence_priv_string(priv_type_text);
+ relkind = get_rel_relkind(sequenceoid);
+ if (relkind == '\0')
+ PG_RETURN_NULL();
+ else if (relkind != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ get_rel_name(sequenceoid))));
+
+ aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_sequence_privilege_id
+ * Check user privileges on a sequence given
+ * sequence oid, and text priv name.
+ * current_user is assumed
+ */
+Datum
+has_sequence_privilege_id(PG_FUNCTION_ARGS)
+{
+ Oid sequenceoid = PG_GETARG_OID(0);
+ text *priv_type_text = PG_GETARG_TEXT_P(1);
+ Oid roleid;
+ AclMode mode;
+ AclResult aclresult;
+ char relkind;
+
+ roleid = GetUserId();
+ mode = convert_sequence_priv_string(priv_type_text);
+ relkind = get_rel_relkind(sequenceoid);
+ if (relkind == '\0')
+ PG_RETURN_NULL();
+ else if (relkind != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ get_rel_name(sequenceoid))));
+
+ aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_sequence_privilege_id_name
+ * Check user privileges on a sequence given
+ * roleid, text sequencename, and text priv name.
+ */
+Datum
+has_sequence_privilege_id_name(PG_FUNCTION_ARGS)
+{
+ Oid roleid = PG_GETARG_OID(0);
+ text *sequencename = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid sequenceoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ mode = convert_sequence_priv_string(priv_type_text);
+ sequenceoid = convert_table_name(sequencename);
+ if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ text_to_cstring(sequencename))));
+
+ aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_sequence_privilege_id_id
+ * Check user privileges on a sequence given
+ * roleid, sequence oid, and text priv name.
+ */
+Datum
+has_sequence_privilege_id_id(PG_FUNCTION_ARGS)
+{
+ Oid roleid = PG_GETARG_OID(0);
+ Oid sequenceoid = PG_GETARG_OID(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ AclMode mode;
+ AclResult aclresult;
+ char relkind;
+
+ mode = convert_sequence_priv_string(priv_type_text);
+ relkind = get_rel_relkind(sequenceoid);
+ if (relkind == '\0')
+ PG_RETURN_NULL();
+ else if (relkind != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ get_rel_name(sequenceoid))));
+
+ aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * convert_sequence_priv_string
+ * Convert text string to AclMode value.
+ */
+static AclMode
+convert_sequence_priv_string(text *priv_type_text)
+{
+ static const priv_map sequence_priv_map[] = {
+ { "USAGE", ACL_USAGE },
+ { "SELECT", ACL_SELECT },
+ { "UPDATE", ACL_UPDATE },
+ { NULL, 0 }
+ };
+
+ return convert_any_priv_string(priv_type_text, sequence_priv_map);
+}
+
/*
* has_any_column_privilege variants