-- read_only.sql: what fuel_ro may and may not do. Run by run.sh, logged in as fuel_ro. \set ON_ERROR_STOP 1 DO $$ DECLARE v text; n integer := 0; has boolean; BEGIN FOREACH v IN ARRAY ARRAY['v_site','v_kpi_measures','v_hour_meter_evidence','v_assumption','v_baseline_version', 'v_baseline_input','v_evidence','v_delivery','v_stock_reading','v_interval','v_runtime', 'v_coverage','v_reconciliation','v_data_quality','v_spec_reference','v_modelled_lph', 'v_electricity_cost','v_imported_calculation'] LOOP EXECUTE format('SELECT count(*) FROM public.%I', v); SELECT EXISTS (SELECT 1 FROM information_schema.columns c WHERE c.table_schema = 'public' AND c.table_name = v AND c.column_name = 'operator_uid') INTO has; IF NOT has THEN RAISE EXCEPTION '% has no operator_uid', v; END IF; n := n + 1; END LOOP; IF n <> 18 THEN RAISE EXCEPTION 'expected 18 views, checked %', n; END IF; IF (SELECT count(*) FROM information_schema.views WHERE table_schema = 'public' AND table_name LIKE 'v\_%') <> 18 THEN RAISE EXCEPTION 'public holds a view this list does not name'; END IF; FOREACH v IN ARRAY ARRAY['fm.holder','fm.operator','licence.licence','licence.plan','licence.licence_event'] LOOP BEGIN EXECUTE format('SELECT count(*) FROM %s', v); RAISE EXCEPTION USING ERRCODE = 'TT001', MESSAGE = v || ' is readable'; EXCEPTION WHEN insufficient_privilege THEN NULL; END; END LOOP; BEGIN EXECUTE 'CREATE TABLE public.written (a integer)'; RAISE EXCEPTION USING ERRCODE = 'TT001', MESSAGE = 'fuel_ro created a table'; EXCEPTION WHEN insufficient_privilege OR read_only_sql_transaction THEN NULL; END; RAISE NOTICE 'read-only role: 18 views readable, each with operator_uid; fm and licence refused; writes refused'; END $$;