-- ============================================================================= -- Audit-Log unveraenderlich machen -- ============================================================================= -- -- Aufruf: npm run db:audit-schutz -- -- Das Audit-Log ist mein Nachweis gegenueber Betreuungsgericht und moeglichen -- Miterben. Es muss deshalb nur anhaengend sein: UPDATE und DELETE werden auf -- Datenbankebene verweigert - auch dann, wenn die Anwendung selbst es -- versuchen wuerde oder jemand mit psql direkt an der Datenbank sitzt. -- -- Einzige Ausnahme: das Aufraeumen von Eintraegen, die aelter als die -- Aufbewahrungsfrist sind. Dafuer gibt es die Funktion -- audit_log_aufraeumen(intervall), die den Schutz kontrolliert umgeht. -- -- Das Skript ist idempotent. -- ============================================================================= CREATE OR REPLACE FUNCTION audit_log_ist_unveraenderlich() RETURNS trigger AS $$ BEGIN -- Die Aufraeum-Funktion setzt diese Sitzungsvariable, um gezielt loeschen -- zu duerfen. Alles andere wird abgewiesen. IF current_setting('betreuung.audit_aufraeumen', true) = 'ja' THEN RETURN OLD; END IF; RAISE EXCEPTION 'Das Audit-Log ist unveraenderlich. % auf audit_log ist nicht zulaessig.', TG_OP USING ERRCODE = 'insufficient_privilege'; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS audit_log_kein_update ON audit_log; CREATE TRIGGER audit_log_kein_update BEFORE UPDATE ON audit_log FOR EACH ROW EXECUTE FUNCTION audit_log_ist_unveraenderlich(); DROP TRIGGER IF EXISTS audit_log_kein_delete ON audit_log; CREATE TRIGGER audit_log_kein_delete BEFORE DELETE ON audit_log FOR EACH ROW EXECUTE FUNCTION audit_log_ist_unveraenderlich(); -- ----------------------------------------------------------------------------- -- Kontrolliertes Aufraeumen alter Eintraege. -- Beispiel: SELECT audit_log_aufraeumen('10 years'); -- ----------------------------------------------------------------------------- CREATE OR REPLACE FUNCTION audit_log_aufraeumen(aufbewahrung interval) RETURNS bigint AS $$ DECLARE geloescht bigint; BEGIN PERFORM set_config('betreuung.audit_aufraeumen', 'ja', true); DELETE FROM audit_log WHERE zeitpunkt < now() - aufbewahrung; GET DIAGNOSTICS geloescht = ROW_COUNT; PERFORM set_config('betreuung.audit_aufraeumen', 'nein', true); RETURN geloescht; END; $$ LANGUAGE plpgsql; -- ----------------------------------------------------------------------------- -- Aufraeumen der Login-Versuche (Rate-Limiting-Historie, 30 Tage genuegen). -- ----------------------------------------------------------------------------- CREATE OR REPLACE FUNCTION login_versuche_aufraeumen() RETURNS bigint AS $$ DECLARE geloescht bigint; BEGIN DELETE FROM login_versuch WHERE zeitpunkt < now() - interval '30 days'; GET DIAGNOSTICS geloescht = ROW_COUNT; RETURN geloescht; END; $$ LANGUAGE plpgsql;