-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathsupabase-setup.sql
More file actions
144 lines (130 loc) · 6.18 KB
/
Copy pathsupabase-setup.sql
File metadata and controls
144 lines (130 loc) · 6.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
-- Solo para una instalación nueva. Para una base existente, usar la migración.
-- Las inscripciones están cerradas; el navegador no tiene acceso a estas tablas.
BEGIN;
-- Script simplificado para crear tabla de voluntarios en Supabase
-- Ejecutar este script completo en el SQL Editor de Supabase
-- 1. Crear la tabla
CREATE TABLE public.volunteers (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
phone TEXT,
city TEXT,
experience TEXT,
interests TEXT[],
availability TEXT,
message TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 2. Crear índices para mejor rendimiento
CREATE INDEX idx_volunteers_email ON volunteers(email);
CREATE INDEX idx_volunteers_city ON volunteers(city);
-- 3. Habilitar Row Level Security
ALTER TABLE volunteers ENABLE ROW LEVEL SECURITY;
-- ============================================
-- TABLA: python_route_registrations
-- ============================================
-- 1. Crear tabla para registros de Python Route
CREATE TABLE public.python_route_registrations (
id SERIAL PRIMARY KEY,
email TEXT NOT NULL,
name TEXT NOT NULL,
phone TEXT,
age INT,
province TEXT NOT NULL,
exact_location TEXT,
group_type TEXT NOT NULL,
workshop_interest TEXT NOT NULL,
programming_experience TEXT NOT NULL,
newsletter_consent BOOLEAN DEFAULT false,
data_protection_accepted BOOLEAN DEFAULT false,
additional_comments TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 2. Crear índices para mejor rendimiento
CREATE INDEX idx_python_route_email ON python_route_registrations(email);
CREATE INDEX idx_python_route_province ON python_route_registrations(province);
CREATE INDEX idx_python_route_created_at ON python_route_registrations(created_at);
-- 3. Habilitar Row Level Security
ALTER TABLE python_route_registrations ENABLE ROW LEVEL SECURITY;
-- Los formularios están desactivados: los roles del navegador no necesitan acceso.
-- No se borra ni se transforma ningún registro existente.
DO $security$
DECLARE
target text;
column_names text;
sequence_name text;
BEGIN
FOREACH target IN ARRAY ARRAY['volunteers', 'python_route_registrations'] LOOP
IF to_regclass(format('public.%I', target)) IS NULL THEN
RAISE NOTICE 'Table public.% absent; no changes required for it', target;
CONTINUE;
END IF;
EXECUTE format('ALTER TABLE public.%I ENABLE ROW LEVEL SECURITY', target);
EXECUTE format('REVOKE ALL PRIVILEGES ON TABLE public.%I FROM PUBLIC, anon, authenticated', target);
-- Los permisos por columna sobreviven a REVOKE a nivel de tabla.
SELECT string_agg(quote_ident(attname), ', ' ORDER BY attnum)
INTO column_names FROM pg_attribute
WHERE attrelid = format('public.%I', target)::regclass
AND attnum > 0 AND NOT attisdropped;
EXECUTE format('REVOKE ALL PRIVILEGES (%s) ON TABLE public.%I FROM PUBLIC, anon, authenticated', column_names, target);
sequence_name := pg_get_serial_sequence(format('public.%I', target), 'id');
IF sequence_name IS NOT NULL THEN
EXECUTE format('REVOKE ALL PRIVILEGES ON SEQUENCE %s FROM PUBLIC, anon, authenticated', sequence_name);
END IF;
EXECUTE format('DROP POLICY IF EXISTS "Enable insert for all users" ON public.%I', target);
EXECUTE format('DROP POLICY IF EXISTS "Enable read for authenticated users only" ON public.%I', target);
EXECUTE format('DROP POLICY IF EXISTS closed_registration_forms ON public.%I', target);
-- Restrictiva: otras políticas permisivas no vuelven a abrir estas tablas.
EXECUTE format('CREATE POLICY closed_registration_forms ON public.%I AS RESTRICTIVE FOR ALL TO anon, authenticated USING (false) WITH CHECK (false)', target);
END LOOP;
END
$security$;
-- NOT VALID preserva datos históricos; sí se aplica a nuevas inserciones y actualizaciones.
DO $constraint$
BEGIN
IF to_regclass('public.volunteers') IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM pg_constraint
WHERE conrelid = to_regclass('public.volunteers')
AND conname = 'volunteers_safe_input') THEN
ALTER TABLE public.volunteers
ADD CONSTRAINT volunteers_safe_input CHECK (
name IS NOT NULL AND char_length(btrim(name)) BETWEEN 1 AND 150
AND email IS NOT NULL AND char_length(email) <= 254
AND email ~ '^[^[:space:]@]+@[^[:space:]@]+[.][^[:space:]@]+$'
AND city IS NOT NULL AND char_length(btrim(city)) BETWEEN 1 AND 100
AND (phone IS NULL OR char_length(phone) <= 40)
AND (experience IS NULL OR char_length(experience) <= 100)
AND (interests IS NULL OR char_length(interests::text) <= 1000)
AND (availability IS NULL OR char_length(availability) <= 100)
AND (message IS NULL OR char_length(message) <= 2000)
) NOT VALID;
END IF;
END
$constraint$;
DO $constraint$
BEGIN
IF to_regclass('public.python_route_registrations') IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM pg_constraint
WHERE conrelid = to_regclass('public.python_route_registrations')
AND conname = 'python_route_registrations_safe_input') THEN
ALTER TABLE public.python_route_registrations
ADD CONSTRAINT python_route_registrations_safe_input CHECK (
name IS NOT NULL AND char_length(btrim(name)) BETWEEN 1 AND 150
AND email IS NOT NULL AND char_length(email) <= 254
AND email ~ '^[^[:space:]@]+@[^[:space:]@]+[.][^[:space:]@]+$'
AND age IS NOT NULL AND age BETWEEN 5 AND 120
AND province IS NOT NULL AND char_length(btrim(province)) BETWEEN 1 AND 100
AND group_type IS NOT NULL AND char_length(btrim(group_type)) BETWEEN 1 AND 150
AND workshop_interest IS NOT NULL AND char_length(btrim(workshop_interest)) BETWEEN 1 AND 150
AND programming_experience IS NOT NULL AND char_length(btrim(programming_experience)) BETWEEN 1 AND 150
AND data_protection_accepted IS TRUE
AND newsletter_consent IS NOT NULL
AND (phone IS NULL OR char_length(phone) <= 40)
AND (exact_location IS NULL OR char_length(exact_location) <= 300)
AND (additional_comments IS NULL OR char_length(additional_comments) <= 2000)
) NOT VALID;
END IF;
END
$constraint$;
COMMIT;