fix reset password
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,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
@@ -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>
|
||||
|
||||
@@ -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; ?>
|
||||
|
||||
Reference in New Issue
Block a user