diff --git a/src/routes/_authenticated/students.$id.tsx b/src/routes/_authenticated/students.$id.tsx index 846d31a..346416d 100644 --- a/src/routes/_authenticated/students.$id.tsx +++ b/src/routes/_authenticated/students.$id.tsx @@ -62,7 +62,7 @@ function StudentDetail() { const { id } = Route.useParams(); const { roles } = useAuth(); const isAdmin = roles.includes("admin"); - const canEdit = isAdmin || roles.includes("parent"); // parents can fill out their own child's profile (RLS-scoped) + const canEdit = isAdmin; // student profile data is admin-edit-only; parents/teachers view only const { data: student } = useQuery({ queryKey: ["student", id], @@ -355,7 +355,7 @@ function ParentAccessSection({ studentId }: { studentId: string }) { }); return (
-

Portal access

Create logins so a parent (can edit this profile) or the student (view-only grades) can sign in.

+

Portal access

Create view-only logins so a parent or the student can sign in to see this student's info and grades.

{studentLogin &&
{studentLogin.full_name || "Student"} Student
{studentLogin.email}
} {(parents ?? []).map((p) =>
{p.full_name || "—"} Parent
{p.email}
)} diff --git a/supabase/migrations/20260719213115_lock_student_data_admin_only.sql b/supabase/migrations/20260719213115_lock_student_data_admin_only.sql new file mode 100644 index 0000000..c246fd0 --- /dev/null +++ b/supabase/migrations/20260719213115_lock_student_data_admin_only.sql @@ -0,0 +1,15 @@ +-- Student profile data (guardians, pickups, curriculum logins) is admin-edit-only. +-- Reads are unchanged (parents/teachers/students keep their "... read" policies); +-- the students table itself is already admin-write via "admins manage students". + +DROP POLICY IF EXISTS "guardians write parent or admin" ON public.student_guardians; +CREATE POLICY "guardians write admin" ON public.student_guardians FOR ALL TO authenticated + USING (public.current_user_has_role('admin')) WITH CHECK (public.current_user_has_role('admin')); + +DROP POLICY IF EXISTS "pickups write parent or admin" ON public.authorized_pickups; +CREATE POLICY "pickups write admin" ON public.authorized_pickups FOR ALL TO authenticated + USING (public.current_user_has_role('admin')) WITH CHECK (public.current_user_has_role('admin')); + +DROP POLICY IF EXISTS "curriculum write parent or admin" ON public.student_curriculum_logins; +CREATE POLICY "curriculum write admin" ON public.student_curriculum_logins FOR ALL TO authenticated + USING (public.current_user_has_role('admin')) WITH CHECK (public.current_user_has_role('admin'));