90 lines
3.7 KiB
PL/PgSQL
90 lines
3.7 KiB
PL/PgSQL
CREATE OR REPLACE FUNCTION set_updated_at() RETURNS trigger AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_case_updated_at') THEN
|
|
CREATE TRIGGER trg_case_updated_at BEFORE UPDATE ON br_case FOR EACH ROW EXECUTE FUNCTION set_updated_at();
|
|
CREATE TRIGGER trg_deadline_updated_at BEFORE UPDATE ON deadline FOR EACH ROW EXECUTE FUNCTION set_updated_at();
|
|
CREATE TRIGGER trg_meeting_updated_at BEFORE UPDATE ON meeting FOR EACH ROW EXECUTE FUNCTION set_updated_at();
|
|
CREATE TRIGGER trg_decision_updated_at BEFORE UPDATE ON decision FOR EACH ROW EXECUTE FUNCTION set_updated_at();
|
|
CREATE TRIGGER trg_task_updated_at BEFORE UPDATE ON task FOR EACH ROW EXECUTE FUNCTION set_updated_at();
|
|
CREATE TRIGGER trg_document_updated_at BEFORE UPDATE ON document_item FOR EACH ROW EXECUTE FUNCTION set_updated_at();
|
|
CREATE TRIGGER trg_template_updated_at BEFORE UPDATE ON template_item FOR EACH ROW EXECUTE FUNCTION set_updated_at();
|
|
END IF;
|
|
END $$;
|
|
|
|
CREATE OR REPLACE FUNCTION audit_if_changed() RETURNS trigger AS $$
|
|
BEGIN
|
|
INSERT INTO audit_log(actor_user_id, action, entity_type, entity_id, metadata)
|
|
VALUES (
|
|
NULL,
|
|
TG_OP,
|
|
TG_TABLE_NAME,
|
|
COALESCE(NEW.id, OLD.id),
|
|
jsonb_build_object('old', to_jsonb(OLD), 'new', to_jsonb(NEW))
|
|
);
|
|
RETURN COALESCE(NEW, OLD);
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_audit_case') THEN
|
|
CREATE TRIGGER trg_audit_case AFTER INSERT OR UPDATE OR DELETE ON br_case FOR EACH ROW EXECUTE FUNCTION audit_if_changed();
|
|
CREATE TRIGGER trg_audit_deadline AFTER INSERT OR UPDATE OR DELETE ON deadline FOR EACH ROW EXECUTE FUNCTION audit_if_changed();
|
|
CREATE TRIGGER trg_audit_meeting AFTER INSERT OR UPDATE OR DELETE ON meeting FOR EACH ROW EXECUTE FUNCTION audit_if_changed();
|
|
CREATE TRIGGER trg_audit_decision AFTER INSERT OR UPDATE OR DELETE ON decision FOR EACH ROW EXECUTE FUNCTION audit_if_changed();
|
|
CREATE TRIGGER trg_audit_task AFTER INSERT OR UPDATE OR DELETE ON task FOR EACH ROW EXECUTE FUNCTION audit_if_changed();
|
|
CREATE TRIGGER trg_audit_document AFTER INSERT OR UPDATE OR DELETE ON document_item FOR EACH ROW EXECUTE FUNCTION audit_if_changed();
|
|
END IF;
|
|
END $$;
|
|
|
|
CREATE OR REPLACE FUNCTION app_user_id() RETURNS BIGINT AS $$
|
|
SELECT COALESCE(NULLIF(current_setting('app.user_id', true), ''), '0')::BIGINT;
|
|
$$ LANGUAGE SQL STABLE;
|
|
|
|
CREATE OR REPLACE FUNCTION app_role() RETURNS TEXT AS $$
|
|
SELECT COALESCE(NULLIF(current_setting('app.user_role', true), ''), 'anonymous');
|
|
$$ LANGUAGE SQL STABLE;
|
|
|
|
CREATE OR REPLACE FUNCTION app_committee_id() RETURNS BIGINT AS $$
|
|
SELECT COALESCE(NULLIF(current_setting('app.committee_id', true), ''), '0')::BIGINT;
|
|
$$ LANGUAGE SQL STABLE;
|
|
|
|
CREATE OR REPLACE FUNCTION can_read_conf_level(level conf_level, owner BIGINT, committee BIGINT) RETURNS BOOLEAN AS $$
|
|
BEGIN
|
|
IF app_role() = 'admin' THEN RETURN TRUE; END IF;
|
|
IF level = 'intern' THEN RETURN TRUE; END IF;
|
|
IF level = 'vertraulich' THEN
|
|
RETURN owner = app_user_id() OR committee = app_committee_id() OR app_role() IN ('chair','secretary');
|
|
END IF;
|
|
RETURN owner = app_user_id() OR app_role() IN ('chair');
|
|
END;
|
|
$$ LANGUAGE plpgsql STABLE;
|
|
|
|
CREATE OR REPLACE VIEW v_case_masked AS
|
|
SELECT
|
|
id,
|
|
case_number,
|
|
title,
|
|
case_type,
|
|
status,
|
|
priority,
|
|
confidentiality_level,
|
|
CASE
|
|
WHEN confidentiality_level = 'streng_vertraulich' AND app_role() NOT IN ('admin','chair') AND owner_user_id <> app_user_id()
|
|
THEN '***'
|
|
ELSE COALESCE(affected_employee_name, '')
|
|
END AS affected_employee_name_masked,
|
|
department,
|
|
committee_id,
|
|
owner_user_id,
|
|
created_at
|
|
FROM br_case
|
|
WHERE deleted_at IS NULL;
|