Let the studio register the students who cannot register themselves
CI / No Debug Code (pull_request) Successful in 4s
CI / Tests (PHP 8.2) (pull_request) Successful in 50s
CI / Tests (PHP 8.1) (pull_request) Successful in 1m3s
CI / Tests (PHP 8.5) (pull_request) Successful in 2m48s
CI / Tests (PHP 8.3) (pull_request) Successful in 3m24s
CI / Coding Standards & Static Analysis (pull_request) Successful in 8m21s
CI / Build Plugin Zip (pull_request) Skipped
CI / No Debug Code (pull_request) Successful in 4s
CI / Tests (PHP 8.2) (pull_request) Successful in 50s
CI / Tests (PHP 8.1) (pull_request) Successful in 1m3s
CI / Tests (PHP 8.5) (pull_request) Successful in 2m48s
CI / Tests (PHP 8.3) (pull_request) Successful in 3m24s
CI / Coding Standards & Static Analysis (pull_request) Successful in 8m21s
CI / Build Plugin Zip (pull_request) Skipped
The Book a lesson for a student panel built its picker from the us_student role but vetted the submission with the book_lesson capability. ChildLoginGate and RegistrationLoginGate withhold that capability from accounts that keep the role, so the panel offered every guardian-managed child and every unapproved signup and then refused them — with a message claiming no student had been chosen, and a form cleared of all five fields. Withholding book_lesson stops those accounts registering in their own name. It was never meant to stop the studio acting for them, which is what the panel is for, and for a child is the only route to a lesson besides their guardian. Guard the student role instead, via a new RoleManager::isStudent() shared with every picker and guard on the staff side so the two cannot drift apart again. Group enrolment gets the same predicate: addDirect() and grantAccess() vetted their posted ids not at all, and would enrol an instructor, an administrator, or an account deleted since the page was drawn — raising a real payment against them for a priced class. Keep a refused booking's fields as submitted, reading the form through one LessonController::submittedBooking() so what gets booked and what is shown again cannot disagree about a field name. A booking that succeeds still leaves an empty form, so the next one does not inherit it. Closes #185 Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01XunBYk2sFEc1oL14sUiuBU
This commit is contained in:
@@ -640,7 +640,15 @@ class GroupClassController {
|
||||
}
|
||||
|
||||
/**
|
||||
* The de-duplicated positive student ids posted from a multi-select.
|
||||
* The de-duplicated student ids posted from a multi-select, keeping only ids
|
||||
* that are actually students.
|
||||
*
|
||||
* The select is built from {@see studentOptions()}, but nothing stops a posted
|
||||
* id naming an instructor, an administrator, or an account deleted since the
|
||||
* page was drawn — and enrolling one would write a roster row, and bill it,
|
||||
* against someone who is not in the class. Vetting here covers both actions at
|
||||
* once, and against the same {@see RoleManager::isStudent()} the picker uses,
|
||||
* so a child or an unapproved signup is still perfectly enrollable.
|
||||
*
|
||||
* @return list<int>
|
||||
*/
|
||||
@@ -650,7 +658,7 @@ class GroupClassController {
|
||||
$raw = (array) ( $_POST['student_ids'] ?? [] );
|
||||
$ids = array_filter( array_map( static fn( mixed $v ): int => absint( Val::int( $v ) ), $raw ) );
|
||||
|
||||
return array_values( array_unique( $ids ) );
|
||||
return array_values( array_filter( array_unique( $ids ), RoleManager::isStudent( ... ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user