\unset ECHO \i test/setup.sql SELECT plan(372); --SELECT * FROM no_plan(); SET client_min_messages = warning; CREATE SCHEMA ha; CREATE TABLE ha.sometab(id INT); CREATE SEQUENCE ha.someseq; CREATE SCHEMA "LOL"; CREATE TABLE "LOL"."ATable"("AColumn" INT); CREATE SEQUENCE "LOL"."ASeq"; -- Include the new schemas in the path. CREATE OR REPLACE FUNCTION set_search_path() returns setof text as $$ BEGIN IF pg_version_num() < 80200 THEN EXECUTE 'SET search_path = ha, "LOL", ' || regexp_replace(current_setting('search_path'), '[$][^,]+,', '') || ', pg_catalog'; RETURN; ELSE EXECUTE 'SET search_path = ha, "LOL", ' || current_setting('search_path') || ', pg_catalog'; END IF; END; $$ language plpgsql; SELECT * FROM set_search_path(); RESET client_min_messages; /****************************************************************************/ -- Test table_privs_are(). SELECT * FROM check_test( table_privs_are( 'ha', 'sometab', current_user, _table_privs(), 'whatever' ), true, 'table_privs_are(sch, tab, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( table_privs_are( 'LOL', 'ATable', current_user, _table_privs(), 'whatever' ), true, 'table_privs_are(LOL, ATable, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( table_privs_are( 'ha', 'sometab', current_user, _table_privs() ), true, 'table_privs_are(sch, tab, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(_table_privs(), ', ') || ' on table ha.sometab' , '' ); SELECT * FROM check_test( table_privs_are( 'LOL', 'ATable', current_user, _table_privs() ), true, 'table_privs_are(LOL, ATable, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(_table_privs(), ', ') || ' on table "LOL"."ATable"' , '' ); SELECT * FROM check_test( table_privs_are( 'sometab', current_user, _table_privs(), 'whatever' ), true, 'table_privs_are(tab, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( table_privs_are( 'ATable', current_user, _table_privs(), 'whatever' ), true, 'table_privs_are(ATable, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( table_privs_are( 'sometab', current_user, _table_privs() ), true, 'table_privs_are(tab, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(_table_privs(), ', ') || ' on table sometab' , '' ); SELECT * FROM check_test( table_privs_are( 'ATable', current_user, _table_privs() ), true, 'table_privs_are(ATable, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(_table_privs(), ', ') || ' on table "ATable"' , '' ); CREATE OR REPLACE FUNCTION run_extra_fails() RETURNS SETOF TEXT LANGUAGE plpgsql AS $$ DECLARE allowed_privs TEXT[]; test_privs TEXT[] := '{}'; missing_privs TEXT[] := '{}'; tap record; last_index INTEGER; BEGIN -- Test table failure. allowed_privs := _table_privs(); last_index := array_upper(allowed_privs, 1); FOR i IN 1..last_index - 2 LOOP test_privs := test_privs || allowed_privs[i]; END LOOP; FOR i IN last_index - 1..last_index LOOP missing_privs := missing_privs || allowed_privs[i]; END LOOP; FOR tap IN SELECT * FROM check_test( table_privs_are( 'ha', 'sometab', current_user, test_privs, 'whatever' ), false, 'table_privs_are(sch, tab, role, some privs, desc)', 'whatever', ' Extra privileges: ' || array_to_string(missing_privs, E'\n ') ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( table_privs_are( 'sometab', current_user, test_privs, 'whatever' ), false, 'table_privs_are(tab, role, some privs, desc)', 'whatever', ' Extra privileges: ' || array_to_string(missing_privs, E'\n ') ) AS b LOOP RETURN NEXT tap.b; END LOOP; END; $$; SELECT * FROM run_extra_fails(); -- Create another role. CREATE USER __someone_else; SELECT * FROM check_test( table_privs_are( 'ha', 'sometab', '__someone_else', _table_privs(), 'whatever' ), false, 'table_privs_are(sch, tab, other, privs, desc)', 'whatever', ' Missing privileges: ' || array_to_string(_table_privs(), E'\n ') ); -- Grant them some permission. GRANT SELECT, INSERT, UPDATE, DELETE ON ha.sometab TO __someone_else; SELECT * FROM check_test( table_privs_are( 'ha', 'sometab', '__someone_else', ARRAY[ 'SELECT', 'INSERT', 'UPDATE', 'DELETE' ], 'whatever'), true, 'table_privs_are(sch, tab, other, privs, desc)', 'whatever', '' ); -- Try a non-existent table. SELECT * FROM check_test( table_privs_are( 'ha', 'nonesuch', current_user, _table_privs(), 'whatever' ), false, 'table_privs_are(sch, tab, role, privs, desc)', 'whatever', ' Table ha.nonesuch does not exist' ); -- Try a non-existent user. SELECT * FROM check_test( table_privs_are( 'ha', 'sometab', '__nonesuch', _table_privs(), 'whatever' ), false, 'table_privs_are(sch, tab, role, privs, desc)', 'whatever', ' Role __nonesuch does not exist' ); -- Test default description with no permissions. SELECT * FROM check_test( table_privs_are( 'ha', 'sometab', '__nonesuch', '{}'::text[] ), false, 'table_privs_are(sch, tab, role, no privs)', 'Role __nonesuch should be granted no privileges on table ha.sometab' , ' Role __nonesuch does not exist' ); SELECT * FROM check_test( table_privs_are( 'sometab', '__nonesuch', '{}'::text[] ), false, 'table_privs_are(tab, role, no privs)', 'Role __nonesuch should be granted no privileges on table sometab' , ' Role __nonesuch does not exist' ); /****************************************************************************/ -- Test database_privileges_are(). SELECT * FROM check_test( database_privs_are( current_database(), current_user, _db_privs(), 'whatever' ), true, 'database_privs_are(db, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( database_privs_are( current_database(), current_user, _db_privs() ), true, 'database_privs_are(db, role, privs, desc)', 'Role ' || current_user || ' should be granted ' || array_to_string(_db_privs(), ', ') || ' on database ' || quote_ident( current_database() ), '' ); -- Try nonexistent database. SELECT * FROM check_test( database_privs_are( '__nonesuch', current_user, _db_privs(), 'whatever' ), false, 'database_privs_are(non-db, role, privs, desc)', 'whatever', ' Database __nonesuch does not exist' ); -- Try nonexistent user. SELECT * FROM check_test( database_privs_are( current_database(), '__noone', _db_privs(), 'whatever' ), false, 'database_privs_are(db, non-role, privs, desc)', 'whatever', ' Role __noone does not exist' ); -- Try another user. SELECT * FROM check_test( database_privs_are( current_database(), '__someone_else', _db_privs(), 'whatever' ), false, 'database_privs_are(db, ungranted, privs, desc)', 'whatever', ' Missing privileges: CREATE' ); -- Try a subset of privs. SELECT * FROM check_test( database_privs_are( current_database(), current_user, CASE WHEN pg_version_num() < 80200 THEN ARRAY['CREATE'] ELSE ARRAY['CREATE', 'CONNECT'] END, 'whatever' ), false, 'database_privs_are(db, ungranted, privs, desc)', 'whatever', ' Extra privileges: TEMPORARY' ); -- Try testing default description for no permissions. SELECT * FROM check_test( database_privs_are( current_database(), '__noone', '{}'::text[] ), false, 'database_privs_are(db, non-role, no privs)', 'Role __noone should be granted no privileges on database ' || quote_ident( current_database() ), ' Role __noone does not exist' ); /****************************************************************************/ -- Test function_privs_are(). CREATE OR REPLACE FUNCTION public.foo(int, text) RETURNS VOID LANGUAGE SQL AS ''; CREATE OR REPLACE FUNCTION "LOL"."DoIt"(int, text) RETURNS VOID LANGUAGE SQL AS ''; SELECT * FROM check_test( function_privs_are( 'public', 'foo', ARRAY['integer', 'text'], current_user, ARRAY['EXECUTE'], 'whatever' ), true, 'function_privs_are(sch, func, args, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( function_privs_are( 'LOL', 'DoIt', ARRAY['integer', 'text'], current_user, ARRAY['EXECUTE'], 'whatever' ), true, 'function_privs_are(LOL, DoIt, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( function_privs_are( 'public', 'foo', ARRAY['integer', 'text'], current_user, ARRAY['EXECUTE'] ), true, 'function_privs_are(sch, func, args, role, privs)', 'Role ' || current_user || ' should be granted EXECUTE on function public.foo(integer, text)' '' ); SELECT * FROM check_test( function_privs_are( 'LOL', 'DoIt', ARRAY['integer', 'text'], current_user, ARRAY['EXECUTE'] ), true, 'function_privs_are(LOL, DoIt, args, role, privs)', 'Role ' || current_user || ' should be granted EXECUTE on function "LOL"."DoIt"(integer, text)' '' ); SELECT * FROM check_test( function_privs_are( 'foo', ARRAY['integer', 'text'], current_user, ARRAY['EXECUTE'], 'whatever' ), true, 'function_privs_are(func, args, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( function_privs_are( 'DoIt', ARRAY['integer', 'text'], current_user, ARRAY['EXECUTE'], 'whatever' ), true, 'function_privs_are(DoIt, args, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( function_privs_are( 'foo', ARRAY['integer', 'text'], current_user, ARRAY['EXECUTE'] ), true, 'function_privs_are(func, args, role, privs)', 'Role ' || current_user || ' should be granted EXECUTE on function foo(integer, text)' '' ); SELECT * FROM check_test( function_privs_are( 'DoIt', ARRAY['integer', 'text'], current_user, ARRAY['EXECUTE'] ), true, 'function_privs_are(DoIt, args, role, privs)', 'Role ' || current_user || ' should be granted EXECUTE on function "DoIt"(integer, text)' '' ); -- Try a nonexistent funtion. SELECT * FROM check_test( function_privs_are( 'public', '__nonesuch', ARRAY['integer', 'text'], current_user, ARRAY['EXECUTE'], 'whatever' ), false, 'function_privs_are(sch, non-func, args, role, privs, desc)', 'whatever', ' Function public.__nonesuch(integer, text) does not exist' ); SELECT * FROM check_test( function_privs_are( '__nonesuch', ARRAY['integer', 'text'], current_user, ARRAY['EXECUTE'], 'whatever' ), false, 'function_privs_are(non-func, args, role, privs, desc)', 'whatever', ' Function __nonesuch(integer, text) does not exist' ); -- Try a nonexistent user. SELECT * FROM check_test( function_privs_are( 'public', 'foo', ARRAY['integer', 'text'], '__noone', ARRAY['EXECUTE'], 'whatever' ), false, 'function_privs_are(sch, func, args, noone, privs, desc)', 'whatever', ' Role __noone does not exist' ); SELECT * FROM check_test( function_privs_are( 'foo', ARRAY['integer', 'text'], '__noone', ARRAY['EXECUTE'], 'whatever' ), false, 'function_privs_are(func, args, noone, privs, desc)', 'whatever', ' Role __noone does not exist' ); -- Try an unprivileged user. SELECT * FROM check_test( function_privs_are( 'public', 'foo', ARRAY['integer', 'text'], '__someone_else', ARRAY['EXECUTE'], 'whatever' ), true, 'function_privs_are(sch, func, args, other, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( function_privs_are( 'foo', ARRAY['integer', 'text'], '__someone_else', ARRAY['EXECUTE'], 'whatever' ), true, 'function_privs_are(func, args, other, privs, desc)', 'whatever', '' ); REVOKE EXECUTE ON FUNCTION public.foo(int, text) FROM PUBLIC; -- Now fail. SELECT * FROM check_test( function_privs_are( 'public', 'foo', ARRAY['integer', 'text'], '__someone_else', ARRAY['EXECUTE'], 'whatever' ), false, 'function_privs_are(sch, func, args, unpriv, privs, desc)', 'whatever', ' Missing privileges: EXECUTE' ); SELECT * FROM check_test( function_privs_are( 'foo', ARRAY['integer', 'text'], '__someone_else', ARRAY['EXECUTE'], 'whatever' ), false, 'function_privs_are(func, args, unpriv, privs, desc)', 'whatever', ' Missing privileges: EXECUTE' ); -- It should work for an empty array. SELECT * FROM check_test( function_privs_are( 'public', 'foo', ARRAY['integer', 'text'], '__someone_else', '{}'::text[], 'whatever' ), true, 'function_privs_are(sch, func, args, unpriv, empty, desc)', 'whatever', '' ); SELECT * FROM check_test( function_privs_are( 'public', 'foo', ARRAY['integer', 'text'], '__someone_else', '{}'::text[] ), true, 'function_privs_are(sch, func, args, unpriv, empty)', 'Role __someone_else should be granted no privileges on function public.foo(integer, text)' '' ); SELECT * FROM check_test( function_privs_are( 'foo', ARRAY['integer', 'text'], '__someone_else', '{}'::text[] ), true, 'function_privs_are(func, args, unpriv, empty)', 'Role __someone_else should be granted no privileges on function foo(integer, text)' '' ); -- Empty for the current user should yeild an extra permission. SELECT * FROM check_test( function_privs_are( 'public', 'foo', ARRAY['integer', 'text'], current_user, '{}'::text[], 'whatever' ), false, 'function_privs_are(sch, func, args, unpriv, privs, desc)', 'whatever', ' Extra privileges: EXECUTE' ); SELECT * FROM check_test( function_privs_are( 'foo', ARRAY['integer', 'text'], current_user, '{}'::text[], 'whatever' ), false, 'function_privs_are(func, args, unpriv, privs, desc)', 'whatever', ' Extra privileges: EXECUTE' ); -- Try a really long function signature. CREATE OR REPLACE FUNCTION public.function_with_a_moderate_signature( anyelement, date, text[], boolean ) RETURNS VOID LANGUAGE SQL AS ''; SELECT * FROM check_test( function_privs_are( 'public', 'function_with_a_moderate_signature', ARRAY['anyelement','date','text[]','boolean'], current_user, ARRAY['EXECUTE'], 'whatever' ), true, 'long function signature', 'whatever', '' ); /****************************************************************************/ -- Test language_privilege_is(). SELECT * FROM check_test( language_privs_are( 'plpgsql', current_user, '{USAGE}', 'whatever' ), true, 'language_privs_are(lang, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( language_privs_are( 'plpgsql', current_user, '{USAGE}' ), true, 'language_privs_are(lang, role, privs, desc)', 'Role ' || current_user || ' should be granted USAGE on language plpgsql', '' ); -- Try nonexistent language. SELECT * FROM check_test( language_privs_are( '__nonesuch', current_user, '{USAGE}', 'whatever' ), false, 'language_privs_are(non-lang, role, privs, desc)', 'whatever', ' Language __nonesuch does not exist' ); -- Try nonexistent user. SELECT * FROM check_test( language_privs_are( 'plpgsql', '__noone', '{USAGE}', 'whatever' ), false, 'language_privs_are(lang, non-role, privs, desc)', 'whatever', ' Role __noone does not exist' ); -- Try another user. REVOKE USAGE ON LANGUAGE plpgsql FROM public; SELECT * FROM check_test( language_privs_are( 'plpgsql', '__someone_else', '{USAGE}', 'whatever' ), false, 'language_privs_are(lang, ungranted, privs, desc)', 'whatever', ' Missing privileges: USAGE' ); -- Try testing default description for no permissions. SELECT * FROM check_test( language_privs_are( 'plpgsql', '__someone_else', '{}'::text[] ), true, 'language_privs_are(lang, role, no privs)', 'Role __someone_else should be granted no privileges on language plpgsql', '' ); /****************************************************************************/ -- Test schema_privileges_are(). SELECT * FROM check_test( schema_privs_are( current_schema(), current_user, ARRAY['CREATE', 'USAGE'], 'whatever' ), true, 'schema_privs_are(schema, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( schema_privs_are( 'LOL', current_user, ARRAY['CREATE', 'USAGE'], 'whatever' ), true, 'schema_privs_are(LOL, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( schema_privs_are( current_schema(), current_user, ARRAY['CREATE', 'USAGE'] ), true, 'schema_privs_are(schema, role, privs, desc)', 'Role ' || current_user || ' should be granted ' || array_to_string(ARRAY['CREATE', 'USAGE'], ', ') || ' on schema ' || current_schema(), '' ); SELECT * FROM check_test( schema_privs_are( 'LOL', current_user, ARRAY['CREATE', 'USAGE'] ), true, 'schema_privs_are(LOL, role, privs, desc)', 'Role ' || current_user || ' should be granted ' || array_to_string(ARRAY['CREATE', 'USAGE'], ', ') || ' on schema "LOL"', '' ); -- Try nonexistent schema. SELECT * FROM check_test( schema_privs_are( '__nonesuch', current_user, ARRAY['CREATE', 'USAGE'], 'whatever' ), false, 'schema_privs_are(non-schema, role, privs, desc)', 'whatever', ' Schema __nonesuch does not exist' ); -- Try nonexistent user. SELECT * FROM check_test( schema_privs_are( current_schema(), '__noone', ARRAY['CREATE', 'USAGE'], 'whatever' ), false, 'schema_privs_are(schema, non-role, privs, desc)', 'whatever', ' Role __noone does not exist' ); -- Try another user. SELECT * FROM check_test( schema_privs_are( current_schema(), '__someone_else', ARRAY['CREATE', 'USAGE'], 'whatever' ), false, 'schema_privs_are(schema, ungranted, privs, desc)', 'whatever', ' Missing privileges: CREATE USAGE' ); -- Try a subset of privs. SELECT * FROM check_test( schema_privs_are( current_schema(), current_user, ARRAY['CREATE'], 'whatever' ), false, 'schema_privs_are(schema, ungranted, privs, desc)', 'whatever', ' Extra privileges: USAGE' ); -- Try testing default description for no permissions. SELECT * FROM check_test( schema_privs_are( current_schema(), '__noone', '{}'::text[] ), false, 'schema_privs_are(schema, non-role, no privs)', 'Role __noone should be granted no privileges on schema ' || current_schema(), ' Role __noone does not exist' ); /****************************************************************************/ -- Test tablespace_privilege_is(). SELECT * FROM check_test( tablespace_privs_are( 'pg_default', current_user, '{CREATE}', 'whatever' ), true, 'tablespace_privs_are(tablespace, role, privs, desc)', 'whatever', '' ); SELECT * FROM check_test( tablespace_privs_are( 'pg_default', current_user, '{CREATE}' ), true, 'tablespace_privs_are(tablespace, role, privs, desc)', 'Role ' || current_user || ' should be granted CREATE on tablespace pg_default', '' ); -- Try nonexistent tablespace. SELECT * FROM check_test( tablespace_privs_are( '__nonesuch', current_user, '{CREATE}', 'whatever' ), false, 'tablespace_privs_are(non-tablespace, role, privs, desc)', 'whatever', ' Tablespace __nonesuch does not exist' ); -- Try nonexistent user. SELECT * FROM check_test( tablespace_privs_are( 'pg_default', '__noone', '{CREATE}', 'whatever' ), false, 'tablespace_privs_are(tablespace, non-role, privs, desc)', 'whatever', ' Role __noone does not exist' ); -- Try another user. REVOKE CREATE ON TABLESPACE pg_default FROM public; SELECT * FROM check_test( tablespace_privs_are( 'pg_default', '__someone_else', '{CREATE}', 'whatever' ), false, 'tablespace_privs_are(tablespace, ungranted, privs, desc)', 'whatever', ' Missing privileges: CREATE' ); -- Try testing default description for no permissions. SELECT * FROM check_test( tablespace_privs_are( 'pg_default', '__someone_else', '{}'::text[] ), true, 'tablespace_privs_are(tablespace, role, no privs)', 'Role __someone_else should be granted no privileges on tablespace pg_default', '' ); /****************************************************************************/ -- Test sequence_privilege_is(). CREATE FUNCTION test_sequence() RETURNS SETOF TEXT AS $$ DECLARE allowed_privs TEXT[]; test_privs TEXT[]; missing_privs TEXT[]; tap record; last_index INTEGER; BEGIN IF pg_version_num() >= 90000 THEN FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'ha', 'someseq', current_user, ARRAY[ 'USAGE', 'SELECT', 'UPDATE' ], 'whatever' ), true, 'sequence_privs_are(sch, seq, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'LOL', 'ASeq', current_user, ARRAY[ 'USAGE', 'SELECT', 'UPDATE' ], 'whatever' ), true, 'sequence_privs_are(LOL, ASeq, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'ha', 'someseq', current_user, ARRAY['USAGE', 'SELECT', 'UPDATE'] ), true, 'sequence_privs_are(sch, seq, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(ARRAY['USAGE', 'SELECT', 'UPDATE'], ', ') || ' on sequence ha.someseq' , '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'LOL', 'ASeq', current_user, ARRAY['USAGE', 'SELECT', 'UPDATE'] ), true, 'sequence_privs_are(sch, seq, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(ARRAY['USAGE', 'SELECT', 'UPDATE'], ', ') || ' on sequence "LOL"."ASeq"' , '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'someseq', current_user, ARRAY[ 'USAGE', 'SELECT', 'UPDATE' ], 'whatever' ), true, 'sequence_privs_are(seq, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'ASeq', current_user, ARRAY[ 'USAGE', 'SELECT', 'UPDATE' ], 'whatever' ), true, 'sequence_privs_are(ASeq, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'someseq', current_user, ARRAY['USAGE', 'SELECT', 'UPDATE'] ), true, 'sequence_privs_are(seq, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(ARRAY['USAGE', 'SELECT', 'UPDATE'], ', ') || ' on sequence someseq' , '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'ASeq', current_user, ARRAY['USAGE', 'SELECT', 'UPDATE'] ), true, 'sequence_privs_are(seq, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(ARRAY['USAGE', 'SELECT', 'UPDATE'], ', ') || ' on sequence "ASeq"' , '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Test sequence failure. allowed_privs := ARRAY['USAGE', 'SELECT', 'UPDATE']; last_index := array_upper(allowed_privs, 1); FOR i IN 1..last_index - 2 LOOP test_privs := test_privs || allowed_privs[i]; END LOOP; FOR i IN last_index - 1..last_index LOOP missing_privs := missing_privs || allowed_privs[i]; END LOOP; FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'ha', 'someseq', current_user, test_privs, 'whatever' ), false, 'sequence_privs_are(sch, seq, role, some privs, desc)', 'whatever', ' Extra privileges: ' || array_to_string(missing_privs, E'\n ') ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'someseq', current_user, test_privs, 'whatever' ), false, 'sequence_privs_are(seq, role, some privs, desc)', 'whatever', ' Extra privileges: ' || array_to_string(missing_privs, E'\n ') ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'ha', 'someseq', '__someone_else', ARRAY[ 'USAGE', 'SELECT', 'UPDATE' ], 'whatever' ), false, 'sequence_privs_are(sch, seq, other, privs, desc)', 'whatever', ' Missing privileges: ' || array_to_string(ARRAY['SELECT', 'UPDATE', 'USAGE'], E'\n ') ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Grant them some permission. GRANT SELECT, UPDATE ON ha.someseq TO __someone_else; FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'ha', 'someseq', '__someone_else', ARRAY[ 'SELECT', 'UPDATE' ], 'whatever'), true, 'sequence_privs_are(sch, seq, other, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try a non-existent sequence. FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'ha', 'nonesuch', current_user, ARRAY[ 'USAGE', 'SELECT', 'UPDATE' ], 'whatever' ), false, 'sequence_privs_are(sch, seq, role, privs, desc)', 'whatever', ' Sequence ha.nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try a non-existent user. FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'ha', 'someseq', '__nonesuch', ARRAY[ 'USAGE', 'SELECT', 'UPDATE' ], 'whatever' ), false, 'sequence_privs_are(sch, seq, role, privs, desc)', 'whatever', ' Role __nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Test default description with no permissions. FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'ha', 'someseq', '__nonesuch', '{}'::text[] ), false, 'sequence_privs_are(sch, seq, role, no privs)', 'Role __nonesuch should be granted no privileges on sequence ha.someseq' , ' Role __nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( sequence_privs_are( 'someseq', '__nonesuch', '{}'::text[] ), false, 'sequence_privs_are(seq, role, no privs)', 'Role __nonesuch should be granted no privileges on sequence someseq' , ' Role __nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; ELSE -- Fake it with pass() and fail(). FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'sequence_privs_are(sch, seq, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'sequence_privs_are(LOL, ASeq, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'sequence_privs_are(sch, seq, role, privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'sequence_privs_are(sch, seq, role, privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'sequence_privs_are(seq, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'sequence_privs_are(ASeq, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'sequence_privs_are(seq, role, privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'sequence_privs_are(seq, role, privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'sequence_privs_are(sch, seq, role, some privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'sequence_privs_are(seq, role, some privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'sequence_privs_are(sch, seq, other, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Grant them some permission. FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'sequence_privs_are(sch, seq, other, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try a non-existent sequence. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'sequence_privs_are(sch, seq, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try a non-existent user. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'sequence_privs_are(sch, seq, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Test default description with no permissions. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'sequence_privs_are(sch, seq, role, no privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'sequence_privs_are(seq, role, no privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; END IF; END; $$ LANGUAGE PLPGSQL; SELECT * FROM test_sequence(); /****************************************************************************/ -- Test any_column_privs_are(). CREATE FUNCTION test_anycols() RETURNS SETOF TEXT AS $$ DECLARE allowed_privs TEXT[]; test_privs TEXT[]; missing_privs TEXT[]; tap record; last_index INTEGER; BEGIN IF pg_version_num() >= 80400 THEN FOR tap IN SELECT * FROM check_test( any_column_privs_are( 'ha', 'sometab', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ], 'whatever' ), true, 'any_column_privs_are(sch, tab, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( any_column_privs_are( 'ha', 'sometab', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ] ), true, 'any_column_privs_are(sch, tab, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(ARRAY['INSERT', 'REFERENCES', 'SELECT', 'UPDATE'], ', ') || ' on any column in ha.sometab' , '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( any_column_privs_are( 'sometab', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ], 'whatever' ), true, 'any_column_privs_are(tab, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( any_column_privs_are( 'sometab', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ] ), true, 'any_column_privs_are(tab, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(ARRAY['INSERT', 'REFERENCES', 'SELECT', 'UPDATE'], ', ') || ' on any column in sometab' , '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Test table failure. allowed_privs := ARRAY['INSERT', 'REFERENCES', 'SELECT', 'UPDATE']; last_index := array_upper(allowed_privs, 1); FOR i IN 1..last_index - 2 LOOP test_privs := test_privs || allowed_privs[i]; END LOOP; FOR i IN last_index - 1..last_index LOOP missing_privs := missing_privs || allowed_privs[i]; END LOOP; FOR tap IN SELECT * FROM check_test( any_column_privs_are( 'ha', 'sometab', current_user, test_privs, 'whatever' ), false, 'any_column_privs_are(sch, tab, role, some privs, desc)', 'whatever', ' Extra privileges: ' || array_to_string(missing_privs, E'\n ') ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( any_column_privs_are( 'sometab', current_user, test_privs, 'whatever' ), false, 'any_column_privs_are(tab, role, some privs, desc)', 'whatever', ' Extra privileges: ' || array_to_string(missing_privs, E'\n ') ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( any_column_privs_are( 'ha', 'sometab', '__someone_else', ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ], 'whatever' ), false, 'any_column_privs_are(sch, tab, other, privs, desc)', 'whatever', ' Missing privileges: ' || array_to_string(ARRAY['REFERENCES'], E'\n ') ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( any_column_privs_are( 'ha', 'sometab', '__someone_else', ARRAY[ 'SELECT', 'INSERT', 'UPDATE' ], 'whatever'), true, 'any_column_privs_are(sch, tab, other, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try a non-existent table. FOR tap IN SELECT * FROM check_test( any_column_privs_are( 'ha', 'nonesuch', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ], 'whatever' ), false, 'any_column_privs_are(sch, tab, role, privs, desc)', 'whatever', ' Table ha.nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try a non-existent user. FOR tap IN SELECT * FROM check_test( any_column_privs_are( 'ha', 'sometab', '__nonesuch', ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ], 'whatever' ), false, 'any_column_privs_are(sch, tab, role, privs, desc)', 'whatever', ' Role __nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Test default description with no permissions. FOR tap IN SELECT * FROM check_test( any_column_privs_are( 'ha', 'sometab', '__nonesuch', '{}'::text[] ), false, 'any_column_privs_are(sch, tab, role, no privs)', 'Role __nonesuch should be granted no privileges on any column in ha.sometab' , ' Role __nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( any_column_privs_are( 'sometab', '__nonesuch', '{}'::text[] ), false, 'any_column_privs_are(tab, role, no privs)', 'Role __nonesuch should be granted no privileges on any column in sometab' , ' Role __nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; ELSE -- Fake it with pass() and fail(). FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'any_column_privs_are(sch, tab, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'any_column_privs_are(sch, tab, role, privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'any_column_privs_are(tab, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'any_column_privs_are(tab, role, privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'any_column_privs_are(sch, tab, role, some privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'any_column_privs_are(tab, role, some privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'any_column_privs_are(sch, tab, other, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'any_column_privs_are(sch, tab, other, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try a non-existent table. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'any_column_privs_are(sch, tab, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try a non-existent user. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'any_column_privs_are(sch, tab, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Test default description with no permissions. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'any_column_privs_are(sch, tab, role, no privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'any_column_privs_are(tab, role, no privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; END IF; END; $$ LANGUAGE PLPGSQL; SELECT * FROM test_anycols(); /****************************************************************************/ -- Test column_privs_are(). CREATE FUNCTION test_cols() RETURNS SETOF TEXT AS $$ DECLARE allowed_privs TEXT[]; test_privs TEXT[]; missing_privs TEXT[]; tap record; last_index INTEGER; BEGIN IF pg_version_num() >= 80400 THEN FOR tap IN SELECT * FROM check_test( column_privs_are( 'ha', 'sometab', 'id', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ], 'whatever' ), true, 'column_privs_are(sch, tab, col, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( column_privs_are( 'LOL', 'ATable', 'AColumn', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ], 'whatever' ), true, 'column_privs_are(LOL, ATable, AColumn, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( column_privs_are( 'ha', 'sometab', 'id', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ] ), true, 'column_privs_are(sch, tab, col, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(ARRAY['INSERT', 'REFERENCES', 'SELECT', 'UPDATE'], ', ') || ' on column ha.sometab.id' , '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( column_privs_are( 'LOL', 'ATable', 'AColumn', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ] ), true, 'column_privs_are(LOL, ATable, AColumn, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(ARRAY['INSERT', 'REFERENCES', 'SELECT', 'UPDATE'], ', ') || ' on column "LOL"."ATable"."AColumn"' , '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( column_privs_are( 'sometab', 'id', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ], 'whatever' ), true, 'column_privs_are(tab, col, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( column_privs_are( 'ATable', 'AColumn', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ], 'whatever' ), true, 'column_privs_are(tab, col, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( column_privs_are( 'sometab', 'id', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ] ), true, 'column_privs_are(tab, col, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(ARRAY['INSERT', 'REFERENCES', 'SELECT', 'UPDATE'], ', ') || ' on column sometab.id' , '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( column_privs_are( 'ATable', 'AColumn', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ] ), true, 'column_privs_are(tab, col, role, privs)', 'Role ' || current_user || ' should be granted ' || array_to_string(ARRAY['INSERT', 'REFERENCES', 'SELECT', 'UPDATE'], ', ') || ' on column "ATable"."AColumn"' , '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Test table failure. allowed_privs := ARRAY['INSERT', 'REFERENCES', 'SELECT', 'UPDATE']; last_index := array_upper(allowed_privs, 1); FOR i IN 1..last_index - 2 LOOP test_privs := test_privs || allowed_privs[i]; END LOOP; FOR i IN last_index - 1..last_index LOOP missing_privs := missing_privs || allowed_privs[i]; END LOOP; FOR tap IN SELECT * FROM check_test( column_privs_are( 'ha', 'sometab', 'id', current_user, test_privs, 'whatever' ), false, 'column_privs_are(sch, tab, role, some privs, desc)', 'whatever', ' Extra privileges: ' || array_to_string(missing_privs, E'\n ') ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( column_privs_are( 'sometab', 'id', current_user, test_privs, 'whatever' ), false, 'column_privs_are(tab, role, some privs, desc)', 'whatever', ' Extra privileges: ' || array_to_string(missing_privs, E'\n ') ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( column_privs_are( 'ha', 'sometab', 'id', '__someone_else', ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ], 'whatever' ), false, 'column_privs_are(sch, tab, other, privs, desc)', 'whatever', ' Missing privileges: ' || array_to_string(ARRAY['REFERENCES'], E'\n ') ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Grant them some permission. EXECUTE 'GRANT SELECT, INSERT, UPDATE (id) ON ha.sometab TO __someone_else;'; FOR tap IN SELECT * FROM check_test( column_privs_are( 'ha', 'sometab', 'id', '__someone_else', ARRAY[ 'SELECT', 'INSERT', 'UPDATE' ], 'whatever'), true, 'column_privs_are(sch, tab, other, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try a non-existent table. FOR tap IN SELECT * FROM check_test( column_privs_are( 'ha', 'nonesuch', 'id', current_user, ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ], 'whatever' ), false, 'column_privs_are(sch, tab, role, privs, desc)', 'whatever', ' Table ha.nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try a non-existent user. FOR tap IN SELECT * FROM check_test( column_privs_are( 'ha', 'sometab', 'id', '__nonesuch', ARRAY[ 'INSERT', 'REFERENCES', 'SELECT', 'UPDATE' ], 'whatever' ), false, 'column_privs_are(sch, tab, role, privs, desc)', 'whatever', ' Role __nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Test default description with no permissions. FOR tap IN SELECT * FROM check_test( column_privs_are( 'ha', 'sometab', 'id', '__nonesuch', '{}'::text[] ), false, 'column_privs_are(sch, tab, role, no privs)', 'Role __nonesuch should be granted no privileges on column ha.sometab.id' , ' Role __nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( column_privs_are( 'sometab', 'id', '__nonesuch', '{}'::text[] ), false, 'column_privs_are(tab, role, no privs)', 'Role __nonesuch should be granted no privileges on column sometab.id' , ' Role __nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; ELSE -- Fake it. FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'column_privs_are(sch, tab, col, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'column_privs_are(LOL, ATable, AColumn, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'column_privs_are(sch, tab, col, role, privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'column_privs_are(LOL, ATable, AColumn, role, privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'column_privs_are(tab, col, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'column_privs_are(tab, col, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'column_privs_are(tab, col, role, privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'column_privs_are(tab, col, role, privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'column_privs_are(sch, tab, role, some privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'column_privs_are(tab, role, some privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'column_privs_are(sch, tab, other, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'column_privs_are(sch, tab, other, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try a non-existent table. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'column_privs_are(sch, tab, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try a non-existent user. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'column_privs_are(sch, tab, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Test default description with no permissions. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'column_privs_are(sch, tab, role, no privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'column_privs_are(tab, role, no privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; END IF; END; $$ LANGUAGE PLPGSQL; SELECT * FROM test_cols(); /****************************************************************************/ -- Test fdw_privs_are(). CREATE FUNCTION test_fdw() RETURNS SETOF TEXT AS $$ DECLARE tap record; BEGIN IF pg_version_num() >= 80400 THEN EXECUTE 'CREATE FOREIGN DATA WRAPPER dummy;'; EXECUTE 'CREATE FOREIGN DATA WRAPPER "SomeFDW";'; FOR tap IN SELECT * FROM check_test( fdw_privs_are( 'dummy', current_user, '{USAGE}', 'whatever' ), true, 'fdw_privs_are(fdw, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fdw_privs_are( 'SomeFDW', current_user, '{USAGE}', 'whatever' ), true, 'fdw_privs_are(SomeFDW, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fdw_privs_are( 'dummy', current_user, '{USAGE}' ), true, 'fdw_privs_are(fdw, role, privs, desc)', 'Role ' || current_user || ' should be granted USAGE on FDW dummy', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( fdw_privs_are( 'SomeFDW', current_user, '{USAGE}' ), true, 'fdw_privs_are(SomeFDW, role, privs, desc)', 'Role ' || current_user || ' should be granted USAGE on FDW "SomeFDW"', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try nonexistent fdw. FOR tap IN SELECT * FROM check_test( fdw_privs_are( '__nonesuch', current_user, '{USAGE}', 'whatever' ), false, 'fdw_privs_are(non-fdw, role, privs, desc)', 'whatever', ' FDW __nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try nonexistent user. FOR tap IN SELECT * FROM check_test( fdw_privs_are( 'dummy', '__noone', '{USAGE}', 'whatever' ), false, 'fdw_privs_are(fdw, non-role, privs, desc)', 'whatever', ' Role __noone does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try another user. FOR tap IN SELECT * FROM check_test( fdw_privs_are( 'dummy', '__someone_else', '{USAGE}', 'whatever' ), false, 'fdw_privs_are(fdw, ungranted, privs, desc)', 'whatever', ' Missing privileges: USAGE' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try testing default description for no permissions. FOR tap IN SELECT * FROM check_test( fdw_privs_are( 'dummy', '__someone_else', '{}'::text[] ), true, 'fdw_privs_are(fdw, role, no privs)', 'Role __someone_else should be granted no privileges on FDW dummy', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; ELSE -- Fake it with pass() and fail(). FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'fdw_privs_are(fdw, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'fdw_privs_are(SomeFDW, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'fdw_privs_are(fdw, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'fdw_privs_are(SomeFDW, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try nonexistent fdw. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'fdw_privs_are(non-fdw, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try nonexistent user. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'fdw_privs_are(fdw, non-role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try another user. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'fdw_privs_are(fdw, ungranted, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try testing default description for no permissions. FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'fdw_privs_are(fdw, role, no privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; END IF; RETURN; END; $$ LANGUAGE plpgsql; SELECT * FROM test_fdw(); CREATE FUNCTION test_server() RETURNS SETOF TEXT AS $$ DECLARE tap record; BEGIN IF pg_version_num() >= 80400 THEN EXECUTE 'CREATE SERVER foo FOREIGN DATA WRAPPER dummy;'; EXECUTE 'CREATE SERVER "SomeServer" FOREIGN DATA WRAPPER "SomeFDW";'; FOR tap IN SELECT * FROM check_test( server_privs_are( 'foo', current_user, '{USAGE}', 'whatever' ), true, 'server_privs_are(server, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( server_privs_are( 'SomeServer', current_user, '{USAGE}', 'whatever' ), true, 'server_privs_are(SomeServer, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( server_privs_are( 'foo', current_user, '{USAGE}' ), true, 'server_privs_are(server, role, privs, desc)', 'Role ' || current_user || ' should be granted USAGE on server foo', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( server_privs_are( 'SomeServer', current_user, '{USAGE}' ), true, 'server_privs_are(SomeServer, role, privs, desc)', 'Role ' || current_user || ' should be granted USAGE on server "SomeServer"', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try nonexistent server. FOR tap IN SELECT * FROM check_test( server_privs_are( '__nonesuch', current_user, '{USAGE}', 'whatever' ), false, 'server_privs_are(non-server, role, privs, desc)', 'whatever', ' Server __nonesuch does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try nonexistent user. FOR tap IN SELECT * FROM check_test( server_privs_are( 'foo', '__noone', '{USAGE}', 'whatever' ), false, 'server_privs_are(server, non-role, privs, desc)', 'whatever', ' Role __noone does not exist' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try another user. FOR tap IN SELECT * FROM check_test( server_privs_are( 'foo', '__someone_else', '{USAGE}', 'whatever' ), false, 'server_privs_are(server, ungranted, privs, desc)', 'whatever', ' Missing privileges: USAGE' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try testing default description for no permissions. FOR tap IN SELECT * FROM check_test( server_privs_are( 'foo', '__someone_else', '{}'::text[] ), true, 'server_privs_are(server, role, no privs)', 'Role __someone_else should be granted no privileges on server foo', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; ELSE -- Fake it with pass() and fail(). FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'server_privs_are(server, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'server_privs_are(SomeServer, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'server_privs_are(server, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'server_privs_are(SomeServer, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try nonexistent server. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'server_privs_are(non-server, role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try nonexistent user. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'server_privs_are(server, non-role, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try another user. FOR tap IN SELECT * FROM check_test( fail('whatever'), false, 'server_privs_are(server, ungranted, privs, desc)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; -- Try testing default description for no permissions. FOR tap IN SELECT * FROM check_test( pass('whatever'), true, 'server_privs_are(server, role, no privs)', 'whatever', '' ) AS b LOOP RETURN NEXT tap.b; END LOOP; END IF; RETURN; END; $$ LANGUAGE plpgsql; SELECT * FROM test_server(); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK;