-- 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();