webhooks.sql 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. BEGIN;
  2. -- Create pg_net extension
  3. CREATE EXTENSION IF NOT EXISTS pg_net SCHEMA extensions;
  4. -- Create briven_functions schema
  5. CREATE SCHEMA briven_functions AUTHORIZATION briven_admin;
  6. GRANT USAGE ON SCHEMA briven_functions TO postgres, anon, authenticated, service_role;
  7. ALTER DEFAULT PRIVILEGES IN SCHEMA briven_functions GRANT ALL ON TABLES TO postgres, anon, authenticated, service_role;
  8. ALTER DEFAULT PRIVILEGES IN SCHEMA briven_functions GRANT ALL ON FUNCTIONS TO postgres, anon, authenticated, service_role;
  9. ALTER DEFAULT PRIVILEGES IN SCHEMA briven_functions GRANT ALL ON SEQUENCES TO postgres, anon, authenticated, service_role;
  10. -- briven_functions.migrations definition
  11. CREATE TABLE briven_functions.migrations (
  12. version text PRIMARY KEY,
  13. inserted_at timestamptz NOT NULL DEFAULT NOW()
  14. );
  15. -- Initial briven_functions migration
  16. INSERT INTO briven_functions.migrations (version) VALUES ('initial');
  17. -- briven_functions.hooks definition
  18. CREATE TABLE briven_functions.hooks (
  19. id bigserial PRIMARY KEY,
  20. hook_table_id integer NOT NULL,
  21. hook_name text NOT NULL,
  22. created_at timestamptz NOT NULL DEFAULT NOW(),
  23. request_id bigint
  24. );
  25. CREATE INDEX briven_functions_hooks_request_id_idx ON briven_functions.hooks USING btree (request_id);
  26. CREATE INDEX briven_functions_hooks_h_table_id_h_name_idx ON briven_functions.hooks USING btree (hook_table_id, hook_name);
  27. COMMENT ON TABLE briven_functions.hooks IS 'Briven Functions Hooks: Audit trail for triggered hooks.';
  28. CREATE FUNCTION briven_functions.http_request()
  29. RETURNS trigger
  30. LANGUAGE plpgsql
  31. AS $function$
  32. DECLARE
  33. request_id bigint;
  34. payload jsonb;
  35. url text := TG_ARGV[0]::text;
  36. method text := TG_ARGV[1]::text;
  37. headers jsonb DEFAULT '{}'::jsonb;
  38. params jsonb DEFAULT '{}'::jsonb;
  39. timeout_ms integer DEFAULT 1000;
  40. BEGIN
  41. IF url IS NULL OR url = 'null' THEN
  42. RAISE EXCEPTION 'url argument is missing';
  43. END IF;
  44. IF method IS NULL OR method = 'null' THEN
  45. RAISE EXCEPTION 'method argument is missing';
  46. END IF;
  47. IF TG_ARGV[2] IS NULL OR TG_ARGV[2] = 'null' THEN
  48. headers = '{"Content-Type": "application/json"}'::jsonb;
  49. ELSE
  50. headers = TG_ARGV[2]::jsonb;
  51. END IF;
  52. IF TG_ARGV[3] IS NULL OR TG_ARGV[3] = 'null' THEN
  53. params = '{}'::jsonb;
  54. ELSE
  55. params = TG_ARGV[3]::jsonb;
  56. END IF;
  57. IF TG_ARGV[4] IS NULL OR TG_ARGV[4] = 'null' THEN
  58. timeout_ms = 1000;
  59. ELSE
  60. timeout_ms = TG_ARGV[4]::integer;
  61. END IF;
  62. CASE
  63. WHEN method = 'GET' THEN
  64. SELECT http_get INTO request_id FROM net.http_get(
  65. url,
  66. params,
  67. headers,
  68. timeout_ms
  69. );
  70. WHEN method = 'POST' THEN
  71. payload = jsonb_build_object(
  72. 'old_record', OLD,
  73. 'record', NEW,
  74. 'type', TG_OP,
  75. 'table', TG_TABLE_NAME,
  76. 'schema', TG_TABLE_SCHEMA
  77. );
  78. SELECT http_post INTO request_id FROM net.http_post(
  79. url,
  80. payload,
  81. params,
  82. headers,
  83. timeout_ms
  84. );
  85. ELSE
  86. RAISE EXCEPTION 'method argument % is invalid', method;
  87. END CASE;
  88. INSERT INTO briven_functions.hooks
  89. (hook_table_id, hook_name, request_id)
  90. VALUES
  91. (TG_RELID, TG_NAME, request_id);
  92. RETURN NEW;
  93. END
  94. $function$;
  95. -- Briven super admin
  96. DO
  97. $$
  98. BEGIN
  99. IF NOT EXISTS (
  100. SELECT 1
  101. FROM pg_roles
  102. WHERE rolname = 'briven_functions_admin'
  103. )
  104. THEN
  105. CREATE USER briven_functions_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION;
  106. END IF;
  107. END
  108. $$;
  109. GRANT ALL PRIVILEGES ON SCHEMA briven_functions TO briven_functions_admin;
  110. GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA briven_functions TO briven_functions_admin;
  111. GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA briven_functions TO briven_functions_admin;
  112. ALTER USER briven_functions_admin SET search_path = "briven_functions";
  113. ALTER table "briven_functions".migrations OWNER TO briven_functions_admin;
  114. ALTER table "briven_functions".hooks OWNER TO briven_functions_admin;
  115. ALTER function "briven_functions".http_request() OWNER TO briven_functions_admin;
  116. GRANT briven_functions_admin TO postgres;
  117. -- Remove unused briven_pg_net_admin role
  118. DO
  119. $$
  120. BEGIN
  121. IF EXISTS (
  122. SELECT 1
  123. FROM pg_roles
  124. WHERE rolname = 'briven_pg_net_admin'
  125. )
  126. THEN
  127. REASSIGN OWNED BY briven_pg_net_admin TO briven_admin;
  128. DROP OWNED BY briven_pg_net_admin;
  129. DROP ROLE briven_pg_net_admin;
  130. END IF;
  131. END
  132. $$;
  133. -- pg_net grants when extension is already enabled
  134. DO
  135. $$
  136. BEGIN
  137. IF EXISTS (
  138. SELECT 1
  139. FROM pg_extension
  140. WHERE extname = 'pg_net'
  141. )
  142. THEN
  143. GRANT USAGE ON SCHEMA net TO briven_functions_admin, postgres, anon, authenticated, service_role;
  144. ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
  145. ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
  146. ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
  147. ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
  148. REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
  149. REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
  150. GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO briven_functions_admin, postgres, anon, authenticated, service_role;
  151. GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO briven_functions_admin, postgres, anon, authenticated, service_role;
  152. END IF;
  153. END
  154. $$;
  155. -- Event trigger for pg_net
  156. CREATE OR REPLACE FUNCTION extensions.grant_pg_net_access()
  157. RETURNS event_trigger
  158. LANGUAGE plpgsql
  159. AS $$
  160. BEGIN
  161. IF EXISTS (
  162. SELECT 1
  163. FROM pg_event_trigger_ddl_commands() AS ev
  164. JOIN pg_extension AS ext
  165. ON ev.objid = ext.oid
  166. WHERE ext.extname = 'pg_net'
  167. )
  168. THEN
  169. GRANT USAGE ON SCHEMA net TO briven_functions_admin, postgres, anon, authenticated, service_role;
  170. ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
  171. ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
  172. ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
  173. ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
  174. REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
  175. REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
  176. GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO briven_functions_admin, postgres, anon, authenticated, service_role;
  177. GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO briven_functions_admin, postgres, anon, authenticated, service_role;
  178. END IF;
  179. END;
  180. $$;
  181. COMMENT ON FUNCTION extensions.grant_pg_net_access IS 'Grants access to pg_net';
  182. DO
  183. $$
  184. BEGIN
  185. IF NOT EXISTS (
  186. SELECT 1
  187. FROM pg_event_trigger
  188. WHERE evtname = 'issue_pg_net_access'
  189. ) THEN
  190. CREATE EVENT TRIGGER issue_pg_net_access ON ddl_command_end WHEN TAG IN ('CREATE EXTENSION')
  191. EXECUTE PROCEDURE extensions.grant_pg_net_access();
  192. END IF;
  193. END
  194. $$;
  195. INSERT INTO briven_functions.migrations (version) VALUES ('20210809183423_update_grants');
  196. ALTER function briven_functions.http_request() SECURITY DEFINER;
  197. ALTER function briven_functions.http_request() SET search_path = briven_functions;
  198. REVOKE ALL ON FUNCTION briven_functions.http_request() FROM PUBLIC;
  199. GRANT EXECUTE ON FUNCTION briven_functions.http_request() TO postgres, anon, authenticated, service_role;
  200. COMMIT;