hs.hsadmin.ng/src/main/resources/db/changelog/020-audit-log.sql

112 lines
4.1 KiB
MySQL
Raw Normal View History

2022-08-24 12:01:54 +02:00
--liquibase formatted sql
-- ============================================================================
--changeset audit-OPERATION-TYPE:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
A type representing a DML operation.
*/
do $$
begin
if not exists(select 1 from pg_type where typname = 'operation') then
create type "operation" as enum ('INSERT', 'UPDATE', 'DELETE', 'TRUNCATE');
end if;
--more types here...
end $$;
--//
-- ============================================================================
--changeset audit-TX-CONTEXT-TABLE:1 endDelimiter:--//
2022-08-24 12:01:54 +02:00
-- ----------------------------------------------------------------------------
/*
A table storing transactions with context data.
2022-08-24 12:01:54 +02:00
*/
create table tx_context
2022-08-24 12:01:54 +02:00
(
txId bigint primary key not null,
txTimestamp timestamp not null,
currentUser varchar(63) not null, -- not the uuid, because users can be deleted
assumedRoles varchar not null, -- not the uuids, because roles can be deleted
currentTask varchar not null
2022-08-24 12:01:54 +02:00
);
create index on tx_context using brin (txTimestamp);
2022-08-24 12:01:54 +02:00
--//
-- ============================================================================
--changeset audit-TX-JOURNAL-TABLE:1 endDelimiter:--//
2022-08-24 12:01:54 +02:00
-- ----------------------------------------------------------------------------
/*
A table storing the transaction audit journal for all target tables it's configured for.
2022-08-24 12:01:54 +02:00
*/
create table tx_journal
(
txId bigint not null references tx_context (txId),
targetTable text not null,
targetUuid uuid not null, -- Assumes that all audited tables have a uuid column.
targetOp operation not null,
targetDelta jsonb
);
create index on tx_journal (targetTable, targetUuid);
--//
-- ============================================================================
--changeset audit-TX-JOURNAL-TRIGGER:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Trigger function for transaction audit journal.
*/
create or replace function tx_journal_trigger()
2022-08-24 12:01:54 +02:00
returns trigger
language plpgsql as $$
begin
insert
into tx_context
values (txid_current(), now(),
currentUser(), assumedRoles(), currentTask())
on conflict do nothing;
2022-08-24 12:01:54 +02:00
case tg_op
when 'INSERT' then insert
into tx_journal
values (txid_current(),
tg_table_name, new.uuid, tg_op::operation,
to_jsonb(new));
when 'UPDATE' then insert
into tx_journal
values (txid_current(),
tg_table_name, old.uuid, tg_op::operation,
jsonb_changes_delta(to_jsonb(old), to_jsonb(new)));
when 'DELETE' then insert
into tx_journal
values (txid_current(),
tg_table_name, old.uuid, 'DELETE'::operation,
null::jsonb);
else raise exception 'Trigger op % not supported for %.', tg_op, tg_table_name;
end case;
2022-08-24 12:01:54 +02:00
return null;
end; $$;
--//
-- ============================================================================
--changeset audit-CREATE-JOURNAL-LOG:1 endDelimiter:--//
2022-08-24 12:01:54 +02:00
-- ----------------------------------------------------------------------------
/*
Trigger function for transaction audit journal.
2022-08-24 12:01:54 +02:00
*/
create or replace procedure create_journal(targetTable varchar)
2022-08-24 12:01:54 +02:00
language plpgsql as $$
declare
createTriggerSQL varchar;
2022-08-24 12:01:54 +02:00
begin
createTriggerSQL = 'CREATE TRIGGER ' || targetTable || '_journal' ||
2022-08-24 12:01:54 +02:00
' AFTER INSERT OR UPDATE OR DELETE ON ' || targetTable ||
' FOR EACH ROW EXECUTE PROCEDURE tx_journal_trigger()';
2022-08-24 12:01:54 +02:00
raise notice 'sql: %', createTriggerSQL;
execute createTriggerSQL;
end; $$;
--//