fix reset password
Deploy to Shared Hosting / Shared hosting deploy (push) Failing after 49s
Tests / PHPUnit (push) Failing after 1m20s

This commit is contained in:
root
2026-08-26 20:45:23 -04:00
parent 9899af7b37
commit a354d78fa9
11 changed files with 88 additions and 25 deletions
+1 -1
View File
@@ -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(
+2 -3
View File
@@ -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 250 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 350 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)) {
+9 -1
View File
@@ -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');
}
+1
View File
@@ -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',
-1
View File
@@ -22,7 +22,6 @@ class StudentModel extends Model
'tuition_paid',
'year_of_registration',
'rfid_tag',
'semester',
'school_year',
'is_active'
];
@@ -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'];
}
@@ -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.';
+1 -1
View File
@@ -1,4 +1,5 @@
<!-- app/Views/errors/custom/blocked.php -->
<?php if (session()->getFlashdata('show_block_modal')): ?>
<div class="modal fade" id="blockedModal" tabindex="-1" aria-labelledby="blockedLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content rounded-4 shadow border-0" style="max-width: 600px; margin: auto;">
@@ -14,7 +15,6 @@
</div>
</div>
<?php if (session()->getFlashdata('show_block_modal')): ?>
<script>
window.addEventListener('DOMContentLoaded', function () {
const modal = new bootstrap.Modal(document.getElementById('blockedModal'));
+2 -2
View File
@@ -39,7 +39,7 @@
<button type="submit">Login</button>
<div class="form-links">
<a href="/register">Register</a>
<a href="/forgot_password">Forgot Password</a>
<a href="<?= site_url('user/forgot_password') ?>">Forgot Password</a>
</div>
</div>
</form>
@@ -48,4 +48,4 @@
</div>
</body>
</html>
</html>
+8 -3
View File
@@ -7,12 +7,17 @@
<?= esc(session()->getFlashdata('error')) ?>
</div>
<?php endif; ?>
<?php if (session()->getFlashdata('success')): ?>
<div class="alert alert-success text-center">
<?= esc(session()->getFlashdata('success')) ?>
</div>
<?php endif; ?>
<!-- Form -->
<form method="post" action="/processForgotPassword" class="text-start" style="max-width: 600px; margin: 0 auto;">
<form method="post" action="<?= site_url('user/forgot_password') ?>" class="text-start" style="max-width: 600px; margin: 0 auto;">
<?= csrf_field() ?>
<div class="text-center mb-4">
<a href="<?= base_url('/') ?>">
<a href="<?= site_url('user/forgot_password') ?>">
<img src="<?= base_url('assets/images/alrahma_logo.png') ?>" alt=""
style="width: 120px; height: 120px; border-radius: 50%; object-fit: contain; background-color: #fff;">
</a>
@@ -43,7 +48,7 @@
<div class="text-center">
<p class="mb-0">Don't have an account?</p>
<a href="/register" class="d-inline-block mt-1">Register now</a>
<a href="<?= site_url('register') ?>" class="d-inline-block mt-1">Register now</a>
</div>
</form>
</div>
@@ -1,4 +1,5 @@
<!-- app/Views/user/password_reset_confirmation.php -->
<?php if (session()->getFlashdata('show_modal')): ?>
<div class="modal fade" id="emailConfirmModal" tabindex="-1" aria-labelledby="emailConfirmLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content rounded-4 shadow border-0" style="max-width: 600px; margin: auto;">
@@ -17,11 +18,10 @@
</div>
</div>
<?php if (session()->getFlashdata('show_modal')): ?>
<script>
window.addEventListener('DOMContentLoaded', function() {
const modal = new bootstrap.Modal(document.getElementById('emailConfirmModal'));
modal.show();
});
</script>
<script>
window.addEventListener('DOMContentLoaded', function() {
const modal = new bootstrap.Modal(document.getElementById('emailConfirmModal'));
modal.show();
});
</script>
<?php endif; ?>