feat(db): consolidated PostgreSQL schema replacing Supabase (Phase 1)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+143
@@ -0,0 +1,143 @@
|
||||
-- =============================================================================
|
||||
-- IMS HSE Incident Management System
|
||||
-- Row Level Security Policies (Phase 1)
|
||||
-- Run AFTER schema.sql (functions used in policies must exist).
|
||||
-- All auth.uid() replaced with app_current_user_id() (GUC-based).
|
||||
-- =============================================================================
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Enable RLS + FORCE ROW LEVEL SECURITY on all 13 tables
|
||||
-- ---------------------------------------------------------------------------
|
||||
ALTER TABLE sites ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE zones ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE trucks ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE incidents ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE evidence_files ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE investigations ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE capa_actions ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE dosh_reports ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE notifications_log ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE audit_log ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE app_settings ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE incident_addenda ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- FORCE RLS so that even the table owner (postgres superuser running as app_user) cannot bypass
|
||||
ALTER TABLE sites FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE zones FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE users FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE trucks FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE incidents FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE evidence_files FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE investigations FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE capa_actions FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE dosh_reports FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE notifications_log FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE audit_log FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE app_settings FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE incident_addenda FORCE ROW LEVEL SECURITY;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Policies — final state (all auth.uid() replaced with app_current_user_id())
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
-- sites
|
||||
CREATE POLICY "sites_read" ON sites FOR SELECT USING (active = true);
|
||||
CREATE POLICY "sites_admin_all" ON sites FOR ALL USING (auth_user_role() = 'admin');
|
||||
|
||||
-- zones
|
||||
CREATE POLICY "zones_read" ON zones FOR SELECT USING (true);
|
||||
CREATE POLICY "zones_admin_all" ON zones FOR ALL USING (auth_user_role() = 'admin');
|
||||
|
||||
-- trucks
|
||||
CREATE POLICY "trucks_read" ON trucks FOR SELECT USING (true);
|
||||
CREATE POLICY "trucks_admin_all" ON trucks FOR ALL USING (auth_user_role() = 'admin');
|
||||
|
||||
-- users
|
||||
CREATE POLICY "users_read_own" ON users FOR SELECT USING (id = app_current_user_id());
|
||||
CREATE POLICY "users_read_elevated" ON users FOR SELECT
|
||||
USING (auth_user_role() IN ('hse', 'admin', 'management', 'supervisor'));
|
||||
CREATE POLICY "users_update_own" ON users FOR UPDATE
|
||||
USING (id = app_current_user_id())
|
||||
WITH CHECK (
|
||||
id = app_current_user_id()
|
||||
AND role = (SELECT role FROM public.users WHERE id = app_current_user_id())
|
||||
);
|
||||
CREATE POLICY "users_admin_all" ON users FOR ALL USING (auth_user_role() = 'admin');
|
||||
|
||||
-- incidents
|
||||
CREATE POLICY "incidents_insert" ON incidents FOR INSERT
|
||||
WITH CHECK (reported_by = app_current_user_id());
|
||||
CREATE POLICY "incidents_read_reporter" ON incidents FOR SELECT
|
||||
USING (reported_by = app_current_user_id());
|
||||
CREATE POLICY "incidents_read_supervisor" ON incidents FOR SELECT
|
||||
USING (auth_user_role() = 'supervisor' AND site_id = auth_user_site_id());
|
||||
CREATE POLICY "incidents_read_elevated" ON incidents FOR SELECT
|
||||
USING (auth_user_role() IN ('hse', 'admin', 'management'));
|
||||
CREATE POLICY "incidents_update_elevated" ON incidents FOR UPDATE
|
||||
USING (auth_user_role() IN ('hse', 'admin', 'supervisor'));
|
||||
|
||||
-- evidence_files
|
||||
CREATE POLICY "evidence_insert" ON evidence_files FOR INSERT
|
||||
WITH CHECK (uploaded_by = app_current_user_id());
|
||||
CREATE POLICY "evidence_read_uploader" ON evidence_files FOR SELECT
|
||||
USING (uploaded_by = app_current_user_id());
|
||||
CREATE POLICY "evidence_read_elevated" ON evidence_files FOR SELECT
|
||||
USING (auth_user_role() IN ('hse', 'admin', 'management', 'supervisor'));
|
||||
-- No DELETE policy: files are never deleted (soft-delete only via `deleted` flag)
|
||||
|
||||
-- investigations
|
||||
CREATE POLICY "investigations_hse_admin" ON investigations FOR ALL
|
||||
USING (auth_user_role() IN ('hse', 'admin'));
|
||||
CREATE POLICY "investigations_read_supervisor" ON investigations FOR SELECT
|
||||
USING (auth_user_role() = 'supervisor');
|
||||
|
||||
-- capa_actions (capa_update_owner is tightened — no department clause)
|
||||
CREATE POLICY "capa_read_owner" ON capa_actions FOR SELECT
|
||||
USING (owner_user_id = app_current_user_id() OR department = auth_user_department());
|
||||
CREATE POLICY "capa_update_owner" ON capa_actions FOR UPDATE
|
||||
USING (owner_user_id = app_current_user_id());
|
||||
CREATE POLICY "capa_read_elevated" ON capa_actions FOR SELECT
|
||||
USING (auth_user_role() IN ('hse', 'admin', 'management', 'supervisor'));
|
||||
CREATE POLICY "capa_hse_admin_all" ON capa_actions FOR ALL
|
||||
USING (auth_user_role() IN ('hse', 'admin'));
|
||||
|
||||
-- dosh_reports
|
||||
CREATE POLICY "dosh_hse_admin" ON dosh_reports FOR ALL
|
||||
USING (auth_user_role() IN ('hse', 'admin'));
|
||||
|
||||
-- notifications_log (final state after migration 19 fix)
|
||||
CREATE POLICY "notifications_insert_elevated" ON notifications_log FOR INSERT
|
||||
WITH CHECK (auth_user_role() IN ('hse', 'admin', 'supervisor'));
|
||||
CREATE POLICY "notifications_read_own" ON notifications_log FOR SELECT
|
||||
USING (recipient_user_id = app_current_user_id());
|
||||
CREATE POLICY "notifications_read_admin" ON notifications_log FOR SELECT
|
||||
USING (auth_user_role() = 'admin');
|
||||
CREATE POLICY "notifications_update_own" ON notifications_log FOR UPDATE
|
||||
USING (recipient_user_id = app_current_user_id())
|
||||
WITH CHECK (recipient_user_id = app_current_user_id());
|
||||
|
||||
-- audit_log
|
||||
CREATE POLICY "audit_read_elevated" ON audit_log FOR SELECT
|
||||
USING (auth_user_role() IN ('hse', 'admin'));
|
||||
|
||||
-- app_settings
|
||||
CREATE POLICY "admin_select_settings" ON app_settings FOR SELECT
|
||||
USING (auth_user_role() = 'admin');
|
||||
CREATE POLICY "admin_update_settings" ON app_settings FOR ALL
|
||||
USING (auth_user_role() = 'admin');
|
||||
|
||||
-- incident_addenda
|
||||
CREATE POLICY "addenda_read" ON incident_addenda FOR SELECT
|
||||
USING (
|
||||
auth_user_role() IN ('hse', 'admin', 'supervisor', 'management')
|
||||
OR EXISTS (
|
||||
SELECT 1 FROM incidents i
|
||||
WHERE i.id = incident_id AND i.reported_by = app_current_user_id()
|
||||
)
|
||||
);
|
||||
CREATE POLICY "addenda_insert" ON incident_addenda FOR INSERT
|
||||
WITH CHECK (
|
||||
author = app_current_user_id()
|
||||
AND auth_user_role() IN ('hse', 'admin', 'supervisor')
|
||||
);
|
||||
Reference in New Issue
Block a user