From a354d78fa98d99f8e39a7ada4cdd2fd6c6f77163 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 26 Aug 2026 20:45:23 -0400 Subject: [PATCH] fix reset password --- app/Config/Routes.php | 2 +- app/Controllers/View/ParentController.php | 5 +- app/Controllers/View/UserController.php | 10 ++- app/Filters/SchoolYearWritableFilter.php | 1 + app/Models/StudentModel.php | 1 - .../EnrollmentRegistrationEmailService.php | 61 +++++++++++++++++-- .../Enrollment/EnrollmentEligibility.php | 2 +- app/Views/errors/custom/blocked.php | 2 +- app/Views/home.php | 4 +- app/Views/user/forgot_password.php | 11 +++- .../user/password_reset_confirmation.php | 14 ++--- 11 files changed, 88 insertions(+), 25 deletions(-) diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 234dbe6..db6d027 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -230,7 +230,7 @@ $routes->get('admin/api/v1/admin/auth/me', 'AuthController::adminAuthMe'); $routes->get('/welcome_back', 'View\UserController::welcomeBack'); $routes->get('user/forgot_password', 'View\UserController::forgotPassword'); //display forgot password form -//$routes->post('user/forgot_password', 'View\UserController::processForgotPassword'); //process the password forgot request +$routes->post('user/forgot_password', 'View\UserController::processForgotPassword'); //process the password forgot request $routes->get('login', 'AuthController::loginMask'); $routes->get( diff --git a/app/Controllers/View/ParentController.php b/app/Controllers/View/ParentController.php index b0551e1..b7c5df3 100644 --- a/app/Controllers/View/ParentController.php +++ b/app/Controllers/View/ParentController.php @@ -933,8 +933,8 @@ class ParentController extends BaseController $errors[] = 'A valid 10-digit home/cell phone number is required.'; } - if ($street === '' || strlen($street) < 2 || strlen($street) > 50 || ! preg_match('/^[A-Za-z0-9.\s\-]+$/', $street)) { - $errors[] = 'Home street address must be 2–50 characters and may contain only letters, numbers, spaces, periods, and hyphens.'; + if ($street === '' || strlen($street) < 3 || strlen($street) > 50 || ! preg_match('/^[A-Za-z0-9.\s\-]+$/', $street)) { + $errors[] = 'Home street address must be 3–50 characters and may contain only letters, numbers, spaces, periods, and hyphens.'; } if ($apt !== '' && (strlen($apt) > 15 || ! preg_match('/^[A-Za-z0-9.\s\-]+$/', $apt))) { @@ -2884,7 +2884,6 @@ class ParentController extends BaseController 'parent_id' => (int) $parentId, 'year_of_registration' => date('Y'), 'school_year' => $schoolYear, - 'semester' => $semester, ]; if (!is_null($isNew)) { diff --git a/app/Controllers/View/UserController.php b/app/Controllers/View/UserController.php index 15444e8..f39ef3c 100644 --- a/app/Controllers/View/UserController.php +++ b/app/Controllers/View/UserController.php @@ -459,6 +459,8 @@ class UserController extends BaseController // --- Handle unknown or unverified email --- if (!$user || (int) $user['is_verified'] === 0) { session()->setFlashdata('success', 'If this email is registered, you will receive a reset link.'); + session()->setFlashdata('show_modal', true); + session()->setFlashdata('email', $email); log_message('info', "Password reset requested for {$email} (user missing or unverified)."); return redirect()->back(); } @@ -478,6 +480,8 @@ class UserController extends BaseController $this->sendResetEmail($email, $token); session()->setFlashdata('success', 'A password reset link has been sent to your email.'); + session()->setFlashdata('show_modal', true); + session()->setFlashdata('email', $email); log_message('info', "Password reset email sent to {$email}"); return redirect()->back(); @@ -633,14 +637,18 @@ class UserController extends BaseController $ipAttemptModel->where('ip_address', $ipAddress)->delete(); } + $this->resetRequestModel->where('ip_address', $ipAddress)->delete(); + // Redirect to a success page with a success message - return view('user/password_set_success'); + return redirect()->to('/user/password_set_success'); } public function passwordSetSuccess() { + $this->resetRequestModel->where('ip_address', $this->request->getIPAddress())->delete(); + return view('user/password_set_success'); } diff --git a/app/Filters/SchoolYearWritableFilter.php b/app/Filters/SchoolYearWritableFilter.php index 5932822..1363806 100644 --- a/app/Filters/SchoolYearWritableFilter.php +++ b/app/Filters/SchoolYearWritableFilter.php @@ -29,6 +29,7 @@ final class SchoolYearWritableFilter implements FilterInterface 'user/select_role', 'set-role', 'processForgotPassword', + 'user/forgot_password', 'user/processResetPassword', 'user/save_password', 'set_authorized_user_password', diff --git a/app/Models/StudentModel.php b/app/Models/StudentModel.php index d9d31e6..7c2ebee 100644 --- a/app/Models/StudentModel.php +++ b/app/Models/StudentModel.php @@ -22,7 +22,6 @@ class StudentModel extends Model 'tuition_paid', 'year_of_registration', 'rfid_tag', - 'semester', 'school_year', 'is_active' ]; diff --git a/app/Services/EnrollmentRegistrationEmailService.php b/app/Services/EnrollmentRegistrationEmailService.php index 89faa9c..7e33a88 100644 --- a/app/Services/EnrollmentRegistrationEmailService.php +++ b/app/Services/EnrollmentRegistrationEmailService.php @@ -187,7 +187,7 @@ final class EnrollmentRegistrationEmailService ); $studentRows[] = $this->studentRow($student, $evaluation, $opens, $deadline, $schoolYear); $studentIds[] = $studentId; - $hasReEnrollmentEligibleStudent = $hasReEnrollmentEligibleStudent || (bool) ($evaluation['can_enroll'] ?? false); + $hasReEnrollmentEligibleStudent = $hasReEnrollmentEligibleStudent || $this->canCompleteParentReEnrollment($evaluation); } $financial = $this->financialSection((int) $family['parent_user_id'], $schoolYear, $previousYear); @@ -215,7 +215,7 @@ final class EnrollmentRegistrationEmailService private function canCompleteParentReEnrollment(array $evaluation): bool { - return (bool) ($evaluation['can_enroll'] ?? false); + return (bool) ($evaluation['parent_enrollment_allowed'] ?? $evaluation['can_enroll'] ?? false); } private function registrationStepsSection(string $opens, string $deadline, bool $include): string @@ -306,7 +306,7 @@ final class EnrollmentRegistrationEmailService return (string) $evaluation['primary_parent_message']; } - if (($evaluation['blockers'] ?? []) !== []) { + if (($evaluation['blockers'] ?? []) !== [] && ! $this->hasOnlyNonBlockingEmailBlockers($evaluation)) { return implode(' ', array_values(array_unique(array_filter(array_map( static fn ($blocker): string => trim((string) $blocker), $evaluation['blockers'] @@ -314,6 +314,7 @@ final class EnrollmentRegistrationEmailService } return match ((string) ($evaluation['deliberation_decision'] ?? '')) { + DeliberationDecision::PASSED => $name . ' has successfully passed ' . $this->currentGradeText($evaluation) . '.', DeliberationDecision::REPEAT_CLASS => 'The deliberation decision for ' . $name . ' is to repeat the current grade. After re-enrollment is completed, the student will remain in the same grade.', DeliberationDecision::MAKE_UP_EXAM => 'The final academic decision for ' . $name . ' is currently pending the result of a make-up exam. This exam is scheduled for ' . $this->makeupExamDateText($schoolYear) . ' from 9:30 AM to 11:00 AM at ISGL.' . "\n" . 'The exam result will determine whether the student advances to the next grade or repeats the current class. Failure to attend the make-up exam will automatically result in the student repeating the class, as no further retake opportunities will be available.' @@ -355,7 +356,13 @@ final class EnrollmentRegistrationEmailService $previousYear ?? '', $schoolYearName ); + $fallbackTotal = (float) ($schoolYear['registration_fee'] ?? 0) + + (float) ($schoolYear['tuition_due_at_registration'] ?? 0) + + (float) ($schoolYear['mandatory_fees'] ?? 0); $total = (float) ($summary['total_enrollment_due'] ?? $summary['amount_due'] ?? 0); + if ($total <= 0.0 && $fallbackTotal > 0.0) { + $total = $fallbackTotal; + } if ($total <= 0.0) { return ''; } @@ -521,7 +528,7 @@ final class EnrollmentRegistrationEmailService private function registrationStatus(array $evaluation): string { - if (($evaluation['can_enroll'] ?? false) === true) { + if ($this->canCompleteParentReEnrollment($evaluation)) { return ($evaluation['deliberation_decision'] ?? '') === DeliberationDecision::MAKE_UP_EXAM ? 'Eligible with pending placement' : 'Eligible'; @@ -543,6 +550,18 @@ final class EnrollmentRegistrationEmailService return 'Not Eligible'; } + if (($evaluation['blockers'] ?? []) !== [] && ! $this->hasOnlyNonBlockingEmailBlockers($evaluation)) { + return 'Not Eligible'; + } + + if (($evaluation['deliberation_decision'] ?? '') === DeliberationDecision::PASSED) { + return 'Eligible'; + } + + if (($evaluation['deliberation_decision'] ?? '') === DeliberationDecision::MAKE_UP_EXAM) { + return 'Eligible with pending placement'; + } + if (($evaluation['blockers'] ?? []) !== []) { return 'Not Eligible'; } @@ -566,6 +585,30 @@ final class EnrollmentRegistrationEmailService return array_values(array_diff($codes, $ignoredCodes)) !== []; } + private function hasOnlyNonBlockingEmailBlockers(array $evaluation): bool + { + $blockers = array_values(array_filter(array_map( + static fn ($blocker): string => strtolower(trim((string) $blocker)), + $evaluation['blockers'] ?? [] + ))); + if ($blockers === []) { + return false; + } + + foreach ($blockers as $blocker) { + if ( + str_contains($blocker, 'registration for the new school year has not opened yet') + || str_contains($blocker, 'passed the highest available grade') + ) { + continue; + } + + return false; + } + + return true; + } + private function studentIssueCode(array $evaluation): string { if (! empty($evaluation['adult_student'])) { @@ -617,12 +660,20 @@ final class EnrollmentRegistrationEmailService private function requiredAction(array $evaluation, string $deadline, string $name = 'The student'): string { - if (($evaluation['can_enroll'] ?? false) === true) { + if ($this->canCompleteParentReEnrollment($evaluation)) { return ($evaluation['deliberation_decision'] ?? '') === DeliberationDecision::MAKE_UP_EXAM ? '' : 'Complete re-enrollment before ' . $deadline . '.'; } + if (($evaluation['deliberation_decision'] ?? '') === DeliberationDecision::MAKE_UP_EXAM && ($evaluation['blockers'] ?? []) === []) { + return ''; + } + + if (($evaluation['deliberation_decision'] ?? '') === DeliberationDecision::PASSED && $this->hasOnlyNonBlockingEmailBlockers($evaluation)) { + return 'Complete re-enrollment before ' . $deadline . '.'; + } + if (! empty($evaluation['primary_parent_message'])) { return (string) $evaluation['primary_parent_message']; } diff --git a/app/Support/Enrollment/EnrollmentEligibility.php b/app/Support/Enrollment/EnrollmentEligibility.php index 9f1444c..3d5806a 100644 --- a/app/Support/Enrollment/EnrollmentEligibility.php +++ b/app/Support/Enrollment/EnrollmentEligibility.php @@ -9,7 +9,7 @@ final class EnrollmentEligibility public const DEFERRED_MESSAGE = 'Re-enrollment cannot currently be completed because the final deliberation decision is deferred. Please contact the school administration for the next required step.'; public const KG_MISSING_DECISION_ELIGIBLE_MESSAGE = 'KG students may complete registration now. Their new-year grade placement will be based on the school age-placement rule.'; public const MISSING_DECISION_MESSAGE = 'Re-enrollment cannot currently be completed because no final deliberation decision is recorded for the student. Registration will become available after the school records a final decision.'; - public const ADULT_STUDENT_MESSAGE = 'This student is over the allowed age for enrollment or re-enrollment at the school. Please contact school administration.'; + public const ADULT_STUDENT_MESSAGE = 'This student will be 18 years old or older on September 1 of the selected school year. A parent or guardian cannot complete registration for this student. Please contact school administration.'; public const ADULT_STUDENT_PARENT_PORTAL_MESSAGE = self::ADULT_STUDENT_MESSAGE; public const WITHDRAWN_PORTAL_MESSAGE = 'This student is currently marked as Withdrawn and cannot be enrolled at this time. Please contact school administration.'; public const SIBLING_PORTAL_MESSAGE = 'Enrollment cannot continue because the family record requires administrative review. Please contact school administration.'; diff --git a/app/Views/errors/custom/blocked.php b/app/Views/errors/custom/blocked.php index 65218de..0cc2c36 100644 --- a/app/Views/errors/custom/blocked.php +++ b/app/Views/errors/custom/blocked.php @@ -1,4 +1,5 @@ +getFlashdata('show_block_modal')): ?>