template-saas-database-v2/migrations/V20260120_003__migrate_audit_logs_DOWN.sql
rckrdmrd 27de049441 [TEMPLATE-SAAS-DB] chore: Update audit schema and add migrations
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 04:38:47 -06:00

164 lines
5.4 KiB
PL/PgSQL

-- ============================================
-- Migration: V20260120_003 - DOWN (Rollback)
-- Description: Revert audit.audit_logs structure to legacy
-- Changes (reversed):
-- - Rename resource_type -> entity_type
-- - Rename resource_id -> entity_id
-- - Remove user_email, actor_type columns
-- - Remove resource_name, severity columns
-- - Remove request_id, session_id columns
-- - Remove endpoint, http_method, response_status, duration_ms columns
-- - Restore changes JSONB from old_values, new_values, changed_fields
-- ============================================
-- DOWN Migration (Rollback)
BEGIN;
-- ============================================
-- 1. Restore 'changes' column from split columns
-- ============================================
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'audit' AND table_name = 'audit_logs' AND column_name = 'old_values'
) AND NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'audit' AND table_name = 'audit_logs' AND column_name = 'changes'
) THEN
-- Add changes column
ALTER TABLE audit.audit_logs ADD COLUMN changes JSONB;
-- Migrate data back into changes
UPDATE audit.audit_logs
SET changes = jsonb_build_object(
'old', COALESCE(old_values, '{}'::jsonb),
'new', COALESCE(new_values, '{}'::jsonb),
'fields', COALESCE(changed_fields, '[]'::jsonb)
)
WHERE old_values IS NOT NULL OR new_values IS NOT NULL OR changed_fields IS NOT NULL;
-- Drop new columns
ALTER TABLE audit.audit_logs DROP COLUMN old_values;
ALTER TABLE audit.audit_logs DROP COLUMN new_values;
ALTER TABLE audit.audit_logs DROP COLUMN changed_fields;
RAISE NOTICE 'Restored changes column from old_values, new_values, changed_fields';
END IF;
END $$;
-- ============================================
-- 2. Remove HTTP context columns
-- ============================================
ALTER TABLE audit.audit_logs DROP COLUMN IF EXISTS duration_ms;
ALTER TABLE audit.audit_logs DROP COLUMN IF EXISTS response_status;
ALTER TABLE audit.audit_logs DROP COLUMN IF EXISTS http_method;
ALTER TABLE audit.audit_logs DROP COLUMN IF EXISTS endpoint;
-- ============================================
-- 3. Remove context columns
-- ============================================
ALTER TABLE audit.audit_logs DROP COLUMN IF EXISTS session_id;
ALTER TABLE audit.audit_logs DROP COLUMN IF EXISTS request_id;
-- ============================================
-- 4. Remove severity column and index
-- ============================================
DROP INDEX IF EXISTS audit.idx_audit_logs_severity;
ALTER TABLE audit.audit_logs DROP COLUMN IF EXISTS severity;
-- ============================================
-- 5. Remove resource_name column
-- ============================================
ALTER TABLE audit.audit_logs DROP COLUMN IF EXISTS resource_name;
-- ============================================
-- 6. Remove actor columns
-- ============================================
ALTER TABLE audit.audit_logs DROP COLUMN IF EXISTS actor_type;
ALTER TABLE audit.audit_logs DROP COLUMN IF EXISTS user_email;
-- ============================================
-- 7. Rename resource_id -> entity_id
-- ============================================
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'audit' AND table_name = 'audit_logs' AND column_name = 'resource_id'
) THEN
ALTER TABLE audit.audit_logs RENAME COLUMN resource_id TO entity_id;
RAISE NOTICE 'Renamed resource_id back to entity_id';
END IF;
END $$;
-- ============================================
-- 8. Rename resource_type -> entity_type
-- ============================================
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'audit' AND table_name = 'audit_logs' AND column_name = 'resource_type'
) THEN
-- Drop new index
DROP INDEX IF EXISTS audit.idx_audit_logs_resource;
-- Rename column
ALTER TABLE audit.audit_logs RENAME COLUMN resource_type TO entity_type;
-- Create old index
CREATE INDEX idx_audit_logs_entity ON audit.audit_logs(tenant_id, entity_type, entity_id);
RAISE NOTICE 'Renamed resource_type back to entity_type';
END IF;
END $$;
-- ============================================
-- 9. Restore original log_event function
-- ============================================
CREATE OR REPLACE FUNCTION audit.log_event(
p_tenant_id UUID,
p_user_id UUID,
p_action audit.action_type,
p_entity_type VARCHAR,
p_entity_id VARCHAR DEFAULT NULL,
p_description TEXT DEFAULT NULL,
p_changes JSONB DEFAULT NULL,
p_metadata JSONB DEFAULT '{}'::jsonb
)
RETURNS UUID AS $$
DECLARE
v_id UUID;
BEGIN
INSERT INTO audit.audit_logs (
tenant_id, user_id, action, entity_type, entity_id,
description, changes, metadata
) VALUES (
p_tenant_id, p_user_id, p_action, p_entity_type, p_entity_id,
p_description, p_changes, p_metadata
) RETURNING id INTO v_id;
RETURN v_id;
END;
$$ LANGUAGE plpgsql;
-- ============================================
-- 10. Update comment
-- ============================================
COMMENT ON COLUMN audit.audit_logs.changes IS 'JSON diff of field changes';
RAISE NOTICE 'Rollback of V20260120_003 completed';
COMMIT;