Hi All,
This is a "proof-of-concept" patch for a new model around role attributes
and fine grained permissions meant to alleviate the current over dependence
on superuser.
This is not yet complete and only serves as a proof-of-concept at this
point, but I wanted to share it in the hopes of receiving comments,
suggestions and general feedback.
The general gist of this patch is as follows:
* New system catalog "pg_permission" that relates role id's to permissions.
* New syntax.
- GRANT <permission> TO <role>
- REVOKE <permission> FROM <role>
where, <permission> is one of an enumerated value, such as "CREATE ROLE" or
"CREATE DATABASE".
* Refactor CREATEDB and NOCREATEDB role attribute to "CREATE DATABASE"
permission set by GRANT or REVOKE.
* Refactor CREATEROLE and NOCREATEROLE role attribute to "CREATE ROLE"
permission set by GRANT or REVOKE.
Again, this is meant to serve as a proof-of-concept. It is not
comprehensive and only demonstrates how this might work with a few already
defined permissions.
I have attached the current patch based on master.
Any comments or feedback would be greatly appreciated.
Thanks,
Adam
--
Adam Brightwell - [email protected]
Database Engineer - www.crunchydatasolutions.com
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
new file mode 100644
index a974bd5..8e4ad25
*** a/src/backend/catalog/Makefile
--- b/src/backend/catalog/Makefile
*************** POSTGRES_BKI_SRCS = $(addprefix $(top_sr
*** 39,45 ****
pg_ts_config.h pg_ts_config_map.h pg_ts_dict.h \
pg_ts_parser.h pg_ts_template.h pg_extension.h \
pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \
! pg_foreign_table.h \
pg_default_acl.h pg_seclabel.h pg_shseclabel.h pg_collation.h pg_range.h \
toasting.h indexing.h \
)
--- 39,45 ----
pg_ts_config.h pg_ts_config_map.h pg_ts_dict.h \
pg_ts_parser.h pg_ts_template.h pg_extension.h \
pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \
! pg_foreign_table.h pg_permission.h \
pg_default_acl.h pg_seclabel.h pg_shseclabel.h pg_collation.h pg_range.h \
toasting.h indexing.h \
)
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
new file mode 100644
index d9745ca..9f4b5df
*** a/src/backend/catalog/aclchk.c
--- b/src/backend/catalog/aclchk.c
***************
*** 42,53 ****
--- 42,55 ----
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
+ #include "catalog/pg_permission.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "commands/dbcommands.h"
+ #include "commands/permission.h"
#include "commands/proclang.h"
#include "commands/tablespace.h"
#include "foreign/foreign.h"
*************** bool
*** 5065,5082 ****
has_createrole_privilege(Oid roleid)
{
bool result = false;
- HeapTuple utup;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
! utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
! if (HeapTupleIsValid(utup))
! {
! result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
! ReleaseSysCache(utup);
! }
return result;
}
--- 5067,5079 ----
has_createrole_privilege(Oid roleid)
{
bool result = false;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
! result = HasPermission(roleid, PERM_CREATE_ROLE);
!
return result;
}
diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile
new file mode 100644
index 22f116b..b98212a
*** a/src/backend/commands/Makefile
--- b/src/backend/commands/Makefile
*************** OBJS = aggregatecmds.o alter.o analyze.o
*** 17,23 ****
dbcommands.o define.o discard.o dropcmds.o \
event_trigger.o explain.o extension.o foreigncmds.o functioncmds.o \
indexcmds.o lockcmds.o matview.o operatorcmds.o opclasscmds.o \
! portalcmds.o prepare.o proclang.o \
schemacmds.o seclabel.o sequence.o tablecmds.o tablespace.o trigger.o \
tsearchcmds.o typecmds.o user.o vacuum.o vacuumlazy.o \
variable.o view.o
--- 17,23 ----
dbcommands.o define.o discard.o dropcmds.o \
event_trigger.o explain.o extension.o foreigncmds.o functioncmds.o \
indexcmds.o lockcmds.o matview.o operatorcmds.o opclasscmds.o \
! permission.o portalcmds.o prepare.o proclang.o \
schemacmds.o seclabel.o sequence.o tablecmds.o tablespace.o trigger.o \
tsearchcmds.o typecmds.o user.o vacuum.o vacuumlazy.o \
variable.o view.o
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
new file mode 100644
index f480be8..ecba8a5
*** a/src/backend/commands/dbcommands.c
--- b/src/backend/commands/dbcommands.c
***************
*** 36,45 ****
--- 36,47 ----
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
#include "catalog/pg_db_role_setting.h"
+ #include "catalog/pg_permission.h"
#include "catalog/pg_tablespace.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
+ #include "commands/permission.h"
#include "commands/seclabel.h"
#include "commands/tablespace.h"
#include "mb/pg_wchar.h"
*************** static bool
*** 1789,1806 ****
have_createdb_privilege(void)
{
bool result = false;
- HeapTuple utup;
/* Superusers can always do everything */
if (superuser())
return true;
! utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(GetUserId()));
! if (HeapTupleIsValid(utup))
! {
! result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreatedb;
! ReleaseSysCache(utup);
! }
return result;
}
--- 1791,1803 ----
have_createdb_privilege(void)
{
bool result = false;
/* Superusers can always do everything */
if (superuser())
return true;
! result = HasPermission(GetUserId(), PERM_CREATE_DATABASE);
!
return result;
}
diff --git a/src/backend/commands/permission.c b/src/backend/commands/permission.c
new file mode 100644
index ...977b7d7
*** a/src/backend/commands/permission.c
--- b/src/backend/commands/permission.c
***************
*** 0 ****
--- 1,254 ----
+ /*-------------------------------------------------------------------------
+ *
+ * permission.c
+ * Commands for manipulating permissions.
+ *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California*
+ *
+ * src/backend/commands/permission.c
+ *
+ *-------------------------------------------------------------------------
+ */
+ #include "postgres.h"
+
+ #include "access/genam.h"
+ #include "access/heapam.h"
+ #include "access/htup_details.h"
+ #include "access/sysattr.h"
+ #include "catalog/dependency.h"
+ #include "catalog/indexing.h"
+ #include "catalog/pg_authid.h"
+ #include "commands/permission.h"
+ #include "nodes/pg_list.h"
+ #include "parser/parse_node.h"
+ #include "utils/acl.h"
+ #include "utils/fmgroids.h"
+ #include "utils/rel.h"
+ #include "utils/syscache.h"
+
+ static void AddPermissionToRole(const char *role_name, Oid role_id,
+ List *permissions);
+ static void RemovePermissionFromRole(const char *role_name, Oid role_id,
+ List *permissions);
+
+ void
+ RemovePermissionById(Oid permission_id)
+ {
+ Relation catalog;
+ ScanKeyData skey;
+ SysScanDesc sscan;
+ HeapTuple tuple;
+
+ /* Find permission. */
+ catalog = heap_open(PermissionRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&skey,
+ ObjectIdAttributeNumber,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(permission_id));
+
+ sscan = systable_beginscan(catalog, PermissionRelationId, true,
+ NULL, 1,&skey);
+
+ tuple = systable_getnext(sscan);
+
+ /* If permission exists, then delete it. */
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "could not find tuple for permission %u", permission_id);
+
+ simple_heap_delete(catalog, &tuple->t_self);
+
+ /* Invalidate Cache */
+ // CacheInvalidateRelcache(catalog);
+
+ /* Clean up */
+ heap_close(catalog, RowExclusiveLock);
+ }
+
+ /*
+ * Grant/Revoke permissions to/from roles.
+ */
+ void
+ GrantPermission(GrantPermissionStmt *stmt)
+ {
+ Oid role_id;
+ char *role_name;
+ ListCell *item;
+
+ foreach(item, stmt->roles)
+ {
+ role_name = strVal(lfirst(item));
+ role_id = get_role_oid(role_name, false);
+
+ if (stmt->is_grant)
+ AddPermissionToRole(role_name, role_id, stmt->permissions);
+ else
+ RemovePermissionFromRole(role_name, role_id, stmt->permissions);
+ }
+ }
+
+ /*
+ * HasPermission
+ * check if a user/role has a permission, true if role permission, otherwise
+ * false.
+ *
+ * role_id - the role to check.
+ * permission - the permission to check.
+ */
+ bool
+ HasPermission(Oid role_id, Permission permission)
+ {
+ bool result = false;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache2(PERMROLEIDPERMID, ObjectIdGetDatum(role_id),
+ Int32GetDatum(permission));
+
+ if (HeapTupleIsValid(tuple))
+ {
+ result = true;
+ ReleaseSysCache(tuple);
+ }
+
+ return result;
+ }
+
+ /*
+ * AddPermissionToRole - Add given permissions to the specified role
+ *
+ * role_name: name of role to add permissions to, only used for error messages.
+ * role_id: OID of the role to add permissions to.
+ * permissions: list of permissions to add to the role.
+ *
+ */
+ static void
+ AddPermissionToRole(const char *role_name, Oid role_id, List *permissions)
+ {
+ Relation pg_permission_rel;
+ Oid permission_id;
+ ScanKeyData skeys[2];
+ SysScanDesc sscan;
+ HeapTuple tuple;
+ Datum new_record[Natts_pg_permission];
+ bool new_record_nulls[Natts_pg_permission];
+ ObjectAddress role_dependency;
+ ObjectAddress permission_dependee;
+ ListCell *item;
+
+ pg_permission_rel = heap_open(PermissionRelationId, RowExclusiveLock);
+
+ foreach(item, permissions)
+ {
+ int permission = lfirst_int(item);
+
+ /* Determine if permission is already set. */
+ ScanKeyInit(&skeys[0],
+ Anum_pg_permission_permroleid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(role_id));
+
+ ScanKeyInit(&skeys[1],
+ Anum_pg_permission_permpermission,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(permission));
+
+ sscan = systable_beginscan(pg_permission_rel, PermissionRoleIdPermIndexId,
+ true, NULL, 2, skeys);
+
+ tuple = systable_getnext(sscan);
+
+ if (!HeapTupleIsValid(tuple))
+ {
+ memset(new_record, 0, sizeof(new_record));
+ memset(new_record_nulls, 0, sizeof(new_record_nulls));
+
+ new_record[Anum_pg_permission_permroleid - 1]
+ = ObjectIdGetDatum(role_id);
+ new_record[Anum_pg_permission_permpermission - 1]
+ = Int32GetDatum(permission);
+
+ tuple = heap_form_tuple(RelationGetDescr(pg_permission_rel),
+ new_record, new_record_nulls);
+
+ permission_id = simple_heap_insert(pg_permission_rel, tuple);
+
+ CatalogUpdateIndexes(pg_permission_rel, tuple);
+
+ /* Record dependencies on role */
+ role_dependency.classId = AuthIdRelationId;
+ role_dependency.objectId = role_id;
+ role_dependency.objectSubId = 0;
+
+ permission_dependee.classId = PermissionRelationId;
+ permission_dependee.objectId = permission_id;
+ permission_dependee.objectSubId = 0;
+
+ recordDependencyOn(&permission_dependee, &role_dependency, DEPENDENCY_AUTO);
+
+ heap_freetuple(tuple);
+ }
+ else
+ elog(NOTICE, "Permission already set for %s.", role_name);
+
+ systable_endscan(sscan);
+ }
+
+ /* Clean up. */
+ heap_close(pg_permission_rel, RowExclusiveLock);
+ }
+
+ /*
+ * RemovePermissionFromRole - Remove given permissions from the specified role
+ *
+ * role_name: name of role to add permissions to, only used for error messages.
+ * role_id: OID of the role to add permissions to.
+ * permissions: list of permissions to add to the role.
+ *
+ */
+ static void
+ RemovePermissionFromRole(const char *role_name, Oid role_id, List *permissions)
+ {
+ Relation pg_permission_rel;
+ ScanKeyData skeys[2];
+ SysScanDesc sscan;
+ HeapTuple tuple;
+ ListCell *item;
+
+ pg_permission_rel = heap_open(PermissionRelationId, RowExclusiveLock);
+
+ foreach(item, permissions)
+ {
+ int permission = lfirst_int(item);
+
+ /* Determine if permission is already set. */
+ ScanKeyInit(&skeys[0],
+ Anum_pg_permission_permroleid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(role_id));
+
+ ScanKeyInit(&skeys[1],
+ Anum_pg_permission_permpermission,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(permission));
+
+ sscan = systable_beginscan(pg_permission_rel, PermissionRoleIdPermIndexId,
+ true, NULL, 2, skeys);
+
+ tuple = systable_getnext(sscan);
+
+ /* If the permission exists, remove it. */
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "Permission is not set for %s.", role_name);
+
+ simple_heap_delete(pg_permission_rel, &tuple->t_self);
+
+ CatalogUpdateIndexes(pg_permission_rel, tuple);
+
+ systable_endscan(sscan);
+ }
+
+ /* Clean up. */
+ heap_close(pg_permission_rel, RowExclusiveLock);
+ }
+
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
new file mode 100644
index 3088578..ed7c17b
*** a/src/backend/nodes/copyfuncs.c
--- b/src/backend/nodes/copyfuncs.c
*************** _copyGrantRoleStmt(const GrantRoleStmt *
*** 2701,2706 ****
--- 2701,2718 ----
return newnode;
}
+ static GrantPermissionStmt *
+ _copyGrantPermissionStmt(const GrantPermissionStmt *from)
+ {
+ GrantPermissionStmt *newnode = makeNode(GrantPermissionStmt);
+
+ COPY_NODE_FIELD(roles);
+ COPY_NODE_FIELD(permissions);
+ COPY_SCALAR_FIELD(is_grant);
+
+ return newnode;
+ }
+
static AlterDefaultPrivilegesStmt *
_copyAlterDefaultPrivilegesStmt(const AlterDefaultPrivilegesStmt *from)
{
*************** copyObject(const void *from)
*** 4291,4296 ****
--- 4303,4311 ----
case T_GrantRoleStmt:
retval = _copyGrantRoleStmt(from);
break;
+ case T_GrantPermissionStmt:
+ retval = _copyGrantPermissionStmt(from);
+ break;
case T_AlterDefaultPrivilegesStmt:
retval = _copyAlterDefaultPrivilegesStmt(from);
break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
new file mode 100644
index 1b07db6..e261bbf
*** a/src/backend/nodes/equalfuncs.c
--- b/src/backend/nodes/equalfuncs.c
*************** _equalGrantRoleStmt(const GrantRoleStmt
*** 1045,1050 ****
--- 1045,1060 ----
}
static bool
+ _equalGrantPermissionStmt(const GrantPermissionStmt *a, const GrantPermissionStmt *b)
+ {
+ COMPARE_NODE_FIELD(roles);
+ COMPARE_NODE_FIELD(permissions);
+ COMPARE_SCALAR_FIELD(is_grant);
+
+ return true;
+ }
+
+ static bool
_equalAlterDefaultPrivilegesStmt(const AlterDefaultPrivilegesStmt *a, const AlterDefaultPrivilegesStmt *b)
{
COMPARE_NODE_FIELD(options);
*************** equal(const void *a, const void *b)
*** 2755,2760 ****
--- 2765,2773 ----
case T_GrantRoleStmt:
retval = _equalGrantRoleStmt(a, b);
break;
+ case T_GrantPermissionStmt:
+ retval = _equalGrantPermissionStmt(a, b);
+ break;
case T_AlterDefaultPrivilegesStmt:
retval = _equalAlterDefaultPrivilegesStmt(a, b);
break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
new file mode 100644
index a113809..d3b6d99
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 51,56 ****
--- 51,57 ----
#include "catalog/index.h"
#include "catalog/namespace.h"
+ #include "catalog/pg_permission.h"
#include "catalog/pg_trigger.h"
#include "commands/defrem.h"
#include "commands/trigger.h"
*************** static Node *makeRecursiveViewSelect(cha
*** 322,327 ****
--- 323,330 ----
%type <str> iso_level opt_encoding
%type <node> grantee
%type <list> grantee_list
+ %type <ival> permission
+ %type <list> permission_list
%type <accesspriv> privilege
%type <list> privileges privilege_list
%type <privtarget> privilege_target
*************** GrantRoleStmt:
*** 6072,6077 ****
--- 6075,6088 ----
n->grantor = $6;
$$ = (Node*)n;
}
+ | GRANT permission_list TO role_list
+ {
+ GrantPermissionStmt *n = makeNode(GrantPermissionStmt);
+ n->is_grant = true;
+ n->permissions = $2;
+ n->roles = $4;
+ $$ = (Node*)n;
+ }
;
RevokeRoleStmt:
*************** RevokeRoleStmt:
*** 6095,6100 ****
--- 6106,6119 ----
n->behavior = $9;
$$ = (Node*)n;
}
+ | REVOKE permission_list FROM role_list
+ {
+ GrantPermissionStmt *n = makeNode(GrantPermissionStmt);
+ n->is_grant = false;
+ n->permissions = $2;
+ n->roles = $4;
+ $$ = (Node*)n;
+ }
;
opt_grant_admin_option: WITH ADMIN OPTION { $$ = TRUE; }
*************** opt_granted_by: GRANTED BY RoleId {
*** 6105,6110 ****
--- 6124,6138 ----
| /*EMPTY*/ { $$ = NULL; }
;
+ permission_list: permission { $$ = list_make1_int($1); }
+ | permission_list ',' permission { $$ = lappend_int($1, $3); }
+ ;
+
+ permission: CREATE DATABASE { $$ = PERM_CREATE_DATABASE; }
+ | CREATE ROLE { $$ = PERM_CREATE_ROLE; }
+ | /*EMPTY*/ { $$ = PERM_INVALID; }
+ ;
+
/*****************************************************************************
*
* ALTER DEFAULT PRIVILEGES statement
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
new file mode 100644
index 07e0b98..58cc8ee
*** a/src/backend/tcop/utility.c
--- b/src/backend/tcop/utility.c
***************
*** 39,44 ****
--- 39,45 ----
#include "commands/extension.h"
#include "commands/matview.h"
#include "commands/lockcmds.h"
+ #include "commands/permission.h"
#include "commands/portalcmds.h"
#include "commands/prepare.h"
#include "commands/proclang.h"
*************** check_xact_readonly(Node *parsetree)
*** 183,188 ****
--- 184,190 ----
case T_DropRoleStmt:
case T_GrantStmt:
case T_GrantRoleStmt:
+ case T_GrantPermissionStmt:
case T_AlterDefaultPrivilegesStmt:
case T_TruncateStmt:
case T_DropOwnedStmt:
*************** standard_ProcessUtility(Node *parsetree,
*** 561,566 ****
--- 563,572 ----
GrantRole((GrantRoleStmt *) parsetree);
break;
+ case T_GrantPermissionStmt:
+ GrantPermission((GrantPermissionStmt *) parsetree);
+ break;
+
case T_CreatedbStmt:
/* no event triggers for global objects */
PreventTransactionChain(isTopLevel, "CREATE DATABASE");
*************** CreateCommandTag(Node *parsetree)
*** 2002,2007 ****
--- 2008,2021 ----
}
break;
+ case T_GrantPermissionStmt:
+ {
+ GrantPermissionStmt *stmt = (GrantPermissionStmt *) parsetree;
+
+ tag = (stmt->is_grant) ? "GRANT PERMISSION" : "REVOKE PERMISSION";
+ }
+ break;
+
case T_GrantRoleStmt:
{
GrantRoleStmt *stmt = (GrantRoleStmt *) parsetree;
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
new file mode 100644
index 94d951c..2d5c7d4
*** a/src/backend/utils/cache/syscache.c
--- b/src/backend/utils/cache/syscache.c
***************
*** 47,52 ****
--- 47,53 ----
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
+ #include "catalog/pg_permission.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_range.h"
#include "catalog/pg_rewrite.h"
*************** static const struct cachedesc cacheinfo[
*** 565,570 ****
--- 566,582 ----
},
8
},
+ {PermissionRelationId, /* PERMROLEIDPERMID */
+ PermissionRoleIdPermIndexId,
+ 2,
+ {
+ Anum_pg_permission_permroleid,
+ Anum_pg_permission_permpermission,
+ 0,
+ 0,
+ },
+ 8
+ },
{ProcedureRelationId, /* PROCNAMEARGSNSP */
ProcedureNameArgsNspIndexId,
3,
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
new file mode 100644
index 59576fd..60e110d
*** a/src/include/catalog/indexing.h
--- b/src/include/catalog/indexing.h
*************** DECLARE_UNIQUE_INDEX(pg_extension_name_i
*** 299,304 ****
--- 299,310 ----
DECLARE_UNIQUE_INDEX(pg_range_rngtypid_index, 3542, on pg_range using btree(rngtypid oid_ops));
#define RangeTypidIndexId 3542
+ DECLARE_UNIQUE_INDEX(pg_permission_oid_index, 6001, on pg_permission using btree(oid oid_ops));
+ #define PermissionOidIndexId 6001
+
+ DECLARE_UNIQUE_INDEX(pg_permission_roleid_index, 6002, on pg_permission using btree(permroleid oid_ops, permpermission int4_ops));
+ #define PermissionRoleIdPermIndexId 6002
+
/* last step of initialization script: build the indexes declared above */
BUILD_INDICES
diff --git a/src/include/catalog/pg_permission.h b/src/include/catalog/pg_permission.h
new file mode 100644
index ...eee670b
*** a/src/include/catalog/pg_permission.h
--- b/src/include/catalog/pg_permission.h
***************
*** 0 ****
--- 1,51 ----
+ /*
+ * pg_permission.h
+ * definition of the system catalog for role permissions (pg_permission)
+ *
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ */
+ #ifndef PG_PERMISSION_H
+ #define PG_PERMISSION_H
+
+ #include "catalog/genbki.h"
+
+ /* ----------------
+ * pg_permission definition. cpp turns this into
+ * typedef struct FormData_pg_permission
+ * ----------------
+ */
+ #define PermissionRelationId 6000
+
+ CATALOG(pg_permission,6000)
+ {
+ Oid permroleid;
+ int32 permpermission;
+ } FormData_pg_permission;
+
+ /* ----------------
+ * Form_pg_permission corresponds to a pointer to a tuple with
+ * the format of pg_permission relation.
+ * ----------------
+ */
+ typedef FormData_pg_permission *Form_pg_permission;
+
+ /*
+ * ----------------
+ * compiler constants for pg_permission
+ * ----------------
+ */
+ #define Natts_pg_permission 2
+ #define Anum_pg_permission_permroleid 1
+ #define Anum_pg_permission_permpermission 2
+
+ typedef enum Permission
+ {
+ PERM_INVALID = -1, /* Invalid Permission */
+ PERM_CREATE_DATABASE = 0, /* CREATE DATABASE */
+ PERM_CREATE_ROLE /* CREATE ROLE */
+ } Permission;
+
+ #endif /* PG_PERMISSION_H */
+
diff --git a/src/include/commands/permission.h b/src/include/commands/permission.h
new file mode 100644
index ...0595e8c
*** a/src/include/commands/permission.h
--- b/src/include/commands/permission.h
***************
*** 0 ****
--- 1,27 ----
+ /*-------------------------------------------------------------------------
+ *
+ * permission.h
+ * prototypes for permission.c.
+ *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/permission.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+ #ifndef PERMISSION_H
+ #define PERMISSION_H
+
+ #include "catalog/pg_permission.h"
+ #include "nodes/parsenodes.h"
+
+ extern void RemovePermissionById(Oid permission_id);
+
+ extern void GrantPermission(GrantPermissionStmt *stmt);
+
+ extern bool HasPermission(Oid role_id, Permission permission);
+
+ #endif /* PERMISSION_H */
+
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
new file mode 100644
index 067c768..6b56981
*** a/src/include/nodes/nodes.h
--- b/src/include/nodes/nodes.h
*************** typedef enum NodeTag
*** 278,283 ****
--- 278,284 ----
T_AlterDomainStmt,
T_SetOperationStmt,
T_GrantStmt,
+ T_GrantPermissionStmt,
T_GrantRoleStmt,
T_AlterDefaultPrivilegesStmt,
T_ClosePortalStmt,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
new file mode 100644
index 8364bef..2b20388
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
*************** typedef struct GrantRoleStmt
*** 1476,1481 ****
--- 1476,1493 ----
} GrantRoleStmt;
/* ----------------------
+ * Grant/Revoke Permission Statement
+ * ----------------------
+ */
+ typedef struct GrantPermissionStmt
+ {
+ NodeTag type;
+ List *permissions; /* list of permissions to be granted/revoked */
+ List *roles; /* list of roles to granted/revoked permission */
+ bool is_grant; /* true = GRANT, false = REVOKE */
+ } GrantPermissionStmt;
+
+ /* ----------------------
* Alter Default Privileges Statement
* ----------------------
*/
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
new file mode 100644
index f97229f..23e4d8a
*** a/src/include/utils/syscache.h
--- b/src/include/utils/syscache.h
*************** enum SysCacheIdentifier
*** 72,77 ****
--- 72,78 ----
OPEROID,
OPFAMILYAMNAMENSP,
OPFAMILYOID,
+ PERMROLEIDPERMID,
PROCNAMEARGSNSP,
PROCOID,
RANGETYPE,
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers