teach/db/006_security_boundaries.sql
Ramon f9b2be8187
Some checks failed
dev - build & deploy naar test / build-and-deploy (push) Failing after 4s
v0.3.03-beta: versterk publieke beveiliging
2026-07-14 12:42:16 +02:00

62 lines
2.1 KiB
PL/PgSQL

-- v0.3.03: tenant-isolatie en security-invarianten ook in PostgreSQL afdwingen.
CREATE INDEX IF NOT EXISTS idx_sessions_expires ON sessions(expires_at);
-- Leerlingwachtwoorden worden voortaan alleen eenmalig in de API-respons getoond.
ALTER TABLE users DROP COLUMN IF EXISTS password_plain;
-- Ruim eventuele historische tenant-kruisingen veilig op vóór de triggers actief worden.
UPDATE users u SET class_id = NULL
WHERE class_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM classes c WHERE c.id = u.class_id AND c.school_id = u.school_id
);
DELETE FROM class_teachers ct
WHERE NOT EXISTS (
SELECT 1 FROM classes c
JOIN users u ON u.id = ct.user_id AND u.school_id = c.school_id
WHERE c.id = ct.class_id
AND (u.role = 'teacher' OR EXISTS (
SELECT 1 FROM user_roles ur WHERE ur.user_id = u.id AND ur.role = 'teacher'
))
);
CREATE OR REPLACE FUNCTION teach_validate_user_class_school()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
IF NEW.class_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM classes c WHERE c.id = NEW.class_id AND c.school_id = NEW.school_id
) THEN
RAISE EXCEPTION 'leerling en klas moeten bij dezelfde school horen';
END IF;
RETURN NEW;
END;
$$;
DROP TRIGGER IF EXISTS trg_users_class_school ON users;
CREATE TRIGGER trg_users_class_school
BEFORE INSERT OR UPDATE OF class_id, school_id ON users
FOR EACH ROW EXECUTE FUNCTION teach_validate_user_class_school();
CREATE OR REPLACE FUNCTION teach_validate_class_teacher()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
IF NOT EXISTS (
SELECT 1
FROM classes c
JOIN users u ON u.id = NEW.user_id AND u.school_id = c.school_id
WHERE c.id = NEW.class_id
AND (u.role = 'teacher' OR EXISTS (
SELECT 1 FROM user_roles ur WHERE ur.user_id = u.id AND ur.role = 'teacher'
))
) THEN
RAISE EXCEPTION 'groepsleiding en klas moeten bij dezelfde school horen';
END IF;
RETURN NEW;
END;
$$;
DROP TRIGGER IF EXISTS trg_class_teachers_tenant ON class_teachers;
CREATE TRIGGER trg_class_teachers_tenant
BEFORE INSERT OR UPDATE ON class_teachers
FOR EACH ROW EXECUTE FUNCTION teach_validate_class_teacher();