mirror of
https://github.com/postgres/postgres.git
synced 2025-04-18 13:44:19 +03:00
There were many calls to construct_array() and deconstruct_array() for built-in types, for example, when dealing with system catalog columns. These all hardcoded the type attributes necessary to pass to these functions. To simplify this a bit, add construct_array_builtin(), deconstruct_array_builtin() as wrappers that centralize this hardcoded knowledge. This simplifies many call sites and reduces the amount of hardcoded stuff that is spread around. Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://www.postgresql.org/message-id/flat/2914356f-9e5f-8c59-2995-5997fc48bcba%40enterprisedb.com
168 lines
4.4 KiB
C
168 lines
4.4 KiB
C
/*--------------------------------------------------------------------------
|
|
*
|
|
* test_rls_hooks.c
|
|
* Code for testing RLS hooks.
|
|
*
|
|
* Copyright (c) 2015-2022, PostgreSQL Global Development Group
|
|
*
|
|
* IDENTIFICATION
|
|
* src/test/modules/test_rls_hooks/test_rls_hooks.c
|
|
*
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "catalog/pg_type.h"
|
|
#include "fmgr.h"
|
|
#include "miscadmin.h"
|
|
#include "nodes/makefuncs.h"
|
|
#include "parser/parse_clause.h"
|
|
#include "parser/parse_collate.h"
|
|
#include "parser/parse_node.h"
|
|
#include "parser/parse_relation.h"
|
|
#include "rewrite/rowsecurity.h"
|
|
#include "test_rls_hooks.h"
|
|
#include "utils/acl.h"
|
|
#include "utils/rel.h"
|
|
#include "utils/relcache.h"
|
|
|
|
PG_MODULE_MAGIC;
|
|
|
|
void _PG_init(void);
|
|
|
|
/* Install hooks */
|
|
void
|
|
_PG_init(void)
|
|
{
|
|
/* Set our hooks */
|
|
row_security_policy_hook_permissive = test_rls_hooks_permissive;
|
|
row_security_policy_hook_restrictive = test_rls_hooks_restrictive;
|
|
}
|
|
|
|
/*
|
|
* Return permissive policies to be added
|
|
*/
|
|
List *
|
|
test_rls_hooks_permissive(CmdType cmdtype, Relation relation)
|
|
{
|
|
List *policies = NIL;
|
|
RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
|
|
Datum role;
|
|
FuncCall *n;
|
|
Node *e;
|
|
ColumnRef *c;
|
|
ParseState *qual_pstate;
|
|
ParseNamespaceItem *nsitem;
|
|
|
|
if (strcmp(RelationGetRelationName(relation), "rls_test_permissive") != 0 &&
|
|
strcmp(RelationGetRelationName(relation), "rls_test_both") != 0)
|
|
return NIL;
|
|
|
|
qual_pstate = make_parsestate(NULL);
|
|
|
|
nsitem = addRangeTableEntryForRelation(qual_pstate,
|
|
relation, AccessShareLock,
|
|
NULL, false, false);
|
|
addNSItemToQuery(qual_pstate, nsitem, false, true, true);
|
|
|
|
role = ObjectIdGetDatum(ACL_ID_PUBLIC);
|
|
|
|
policy->policy_name = pstrdup("extension policy");
|
|
policy->polcmd = '*';
|
|
policy->roles = construct_array_builtin(&role, 1, OIDOID);
|
|
|
|
/*
|
|
* policy->qual = (Expr *) makeConst(BOOLOID, -1, InvalidOid,
|
|
* sizeof(bool), BoolGetDatum(true), false, true);
|
|
*/
|
|
|
|
n = makeFuncCall(list_make2(makeString("pg_catalog"),
|
|
makeString("current_user")),
|
|
NIL,
|
|
COERCE_EXPLICIT_CALL,
|
|
-1);
|
|
|
|
c = makeNode(ColumnRef);
|
|
c->fields = list_make1(makeString("username"));
|
|
c->location = 0;
|
|
|
|
e = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) n, (Node *) c, 0);
|
|
|
|
policy->qual = (Expr *) transformWhereClause(qual_pstate, copyObject(e),
|
|
EXPR_KIND_POLICY,
|
|
"POLICY");
|
|
/* Fix up collation information */
|
|
assign_expr_collations(qual_pstate, (Node *) policy->qual);
|
|
|
|
policy->with_check_qual = copyObject(policy->qual);
|
|
policy->hassublinks = false;
|
|
|
|
policies = list_make1(policy);
|
|
|
|
return policies;
|
|
}
|
|
|
|
/*
|
|
* Return restrictive policies to be added
|
|
*
|
|
* Note that a permissive policy must exist or the default-deny policy
|
|
* will be included and nothing will be visible. If no filtering should
|
|
* be done except for the restrictive policy, then a single "USING (true)"
|
|
* permissive policy can be used; see the regression tests.
|
|
*/
|
|
List *
|
|
test_rls_hooks_restrictive(CmdType cmdtype, Relation relation)
|
|
{
|
|
List *policies = NIL;
|
|
RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
|
|
Datum role;
|
|
FuncCall *n;
|
|
Node *e;
|
|
ColumnRef *c;
|
|
ParseState *qual_pstate;
|
|
ParseNamespaceItem *nsitem;
|
|
|
|
if (strcmp(RelationGetRelationName(relation), "rls_test_restrictive") != 0 &&
|
|
strcmp(RelationGetRelationName(relation), "rls_test_both") != 0)
|
|
return NIL;
|
|
|
|
qual_pstate = make_parsestate(NULL);
|
|
|
|
nsitem = addRangeTableEntryForRelation(qual_pstate,
|
|
relation, AccessShareLock,
|
|
NULL, false, false);
|
|
addNSItemToQuery(qual_pstate, nsitem, false, true, true);
|
|
|
|
role = ObjectIdGetDatum(ACL_ID_PUBLIC);
|
|
|
|
policy->policy_name = pstrdup("extension policy");
|
|
policy->polcmd = '*';
|
|
policy->roles = construct_array_builtin(&role, 1, OIDOID);
|
|
|
|
n = makeFuncCall(list_make2(makeString("pg_catalog"),
|
|
makeString("current_user")),
|
|
NIL,
|
|
COERCE_EXPLICIT_CALL,
|
|
-1);
|
|
|
|
c = makeNode(ColumnRef);
|
|
c->fields = list_make1(makeString("supervisor"));
|
|
c->location = 0;
|
|
|
|
e = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) n, (Node *) c, 0);
|
|
|
|
policy->qual = (Expr *) transformWhereClause(qual_pstate, copyObject(e),
|
|
EXPR_KIND_POLICY,
|
|
"POLICY");
|
|
/* Fix up collation information */
|
|
assign_expr_collations(qual_pstate, (Node *) policy->qual);
|
|
|
|
policy->with_check_qual = copyObject(policy->qual);
|
|
policy->hassublinks = false;
|
|
|
|
policies = list_make1(policy);
|
|
|
|
return policies;
|
|
}
|