fix enrollment logic, add financial aid, fix class distribution
Tests / PHPUnit (push) Failing after 1m6s

This commit is contained in:
root
2026-08-15 15:07:16 -04:00
parent c12bb59372
commit 4603d9ced2
95 changed files with 6892 additions and 1295 deletions
+12
View File
@@ -215,4 +215,16 @@ class App extends BaseConfig
// Sessions (also in App.php)
public string $sessionCookieName = '__Host-ci_session';
public bool $sessionRegenerateDestroy = true;
public function __construct()
{
parent::__construct();
$isProduction = ENVIRONMENT === 'production';
$this->forceGlobalSecureRequests = $isProduction;
$this->cookieSecure = $isProduction;
if (! $isProduction) {
$this->cookiePrefix = '';
$this->sessionCookieName = 'ci_session';
}
}
}
+9
View File
@@ -56,6 +56,15 @@ class Cookie extends BaseConfig
*/
public bool $secure = false;
public function __construct()
{
parent::__construct();
$this->secure = ENVIRONMENT === 'production';
if ($this->secure) {
$this->prefix = '__Host-';
}
}
/**
* --------------------------------------------------------------------------
* Cookie HTTPOnly
+2 -2
View File
@@ -34,7 +34,7 @@ class Cors extends BaseConfig
* - ['http://localhost:8080']
* - ['https://www.example.com']
*/
'allowedOrigins' => ['*'], // Allow all origins for mobile apps
'allowedOrigins' => ['*'],
/**
* Origin regex patterns for the `Access-Control-Allow-Origin` header.
@@ -57,7 +57,7 @@ class Cors extends BaseConfig
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
*/
'supportsCredentials' => true, // Enable for mobile apps using cookies/auth
'supportsCredentials' => false,
/**
* Set headers to allow.
+1 -1
View File
@@ -29,7 +29,7 @@ class Database extends Config
'DBDriver' => env('database.default.DBDriver', 'MySQLi'),
'DBPrefix' => '',
'pConnect' => false,
'DBDebug' => (ENVIRONMENT !== 'development'),
'DBDebug' => (ENVIRONMENT === 'development'),
'charset' => 'utf8',
'DBCollat' => 'utf8_general_ci',
'swapPre' => '',
+9
View File
@@ -23,6 +23,15 @@ class Encryption extends BaseConfig
*/
public string $key = '';
public function __construct()
{
parent::__construct();
$fromEnv = (string) env('encryption.key', env('ENCRYPTION_KEY', ''));
if ($fromEnv !== '') {
$this->key = $fromEnv;
}
}
/**
* --------------------------------------------------------------------------
* Encryption Driver to Use
-4
View File
@@ -50,10 +50,6 @@ class Filters extends BaseConfig
'invalidchars',
'schoolYearWritable',
'csrf' => ['except' => [
// WhatsApp membership management (legacy allowances retained)
'whatsapp/update-membership',
'index.php/whatsapp/update-membership',
// Attendance management AJAX saves
'attendance/update',
'index.php/attendance/update',
+99 -93
View File
@@ -115,6 +115,12 @@ $routes->post('administrator/enrollment-admin/flags/(:num)/resolve', 'View\Enrol
$routes->post('administrator/enrollment-admin/flags/(:num)/assign-class', 'View\EnrollmentAdminController::assignClass/$1', ['filter' => 'auth:admin']);
$routes->post('administrator/enrollment-admin/flags/(:num)/makeup-promotion', 'View\EnrollmentAdminController::confirmMakeupPromotion/$1', ['filter' => 'auth:admin']);
$routes->post('administrator/enrollment-admin/flags/(:num)/approve-exception', 'View\EnrollmentAdminController::approveException/$1', ['filter' => 'auth:admin']);
$routes->post('administrator/enrollment-admin/exceptions/create', 'View\EnrollmentAdminController::createException', ['filter' => 'auth:admin']);
$routes->post('administrator/enrollment-admin/exceptions/(:num)/revoke', 'View\EnrollmentAdminController::revokeException/$1', ['filter' => 'auth:admin']);
$routes->get('administrator/financial-aid', 'Administrator\FinancialAidController::index', ['filter' => 'auth:admin|administrator|principal|oversee_financial_aid']);
$routes->get('administrator/financial-aid/(:num)', 'Administrator\FinancialAidController::show/$1', ['filter' => 'auth:admin|administrator|principal|oversee_financial_aid']);
$routes->post('administrator/financial-aid/(:num)/approve', 'Administrator\FinancialAidController::approve/$1', ['filter' => 'auth:admin|administrator|principal|oversee_financial_aid']);
$routes->post('administrator/financial-aid/(:num)/deny', 'Administrator\FinancialAidController::deny/$1', ['filter' => 'auth:admin|administrator|principal|oversee_financial_aid']);
// API for report card meta (students, class sections, school years)
$routes->get('api/printables/report-card/meta', 'View\ReportCardsController::reportCardMeta', ['filter' => 'auth']);
$routes->get('api/printables/report-card/completeness', 'View\ReportCardsController::reportCardCompleteness', ['filter' => 'auth']);
@@ -212,6 +218,7 @@ $routes->get('/classes', 'View\UserController::classes'); // Classes page route
$routes->get('/contact', 'View\UserController::contact'); // Contact Us page route
$routes->post('/user/login', 'AuthController::login');
$routes->post('api/login', 'AuthController::apiLogin');
$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
@@ -571,32 +578,29 @@ $routes->post('grading/release-scores', 'View\GradingController::toggleParentSco
$routes->post('grading/refresh-semester-scores', 'View\GradingController::refreshSemesterScores', ['filter' => 'auth:read']);
// Event admin routes
$routes->get('administrator/events', 'View\EventController::index');
$routes->get('administrator/events/create', 'View\EventController::create'); // show create form
$routes->post('administrator/events/create', 'View\EventController::create'); // handle event create submission
// Route to show form and handle POST in same controller method
$routes->match(['get', 'post'], 'administrator/events/edit/(:num)', 'View\EventController::edit/$1');
$routes->post('administrator/events/delete/(:num)', 'View\EventController::delete/$1'); // handle delete
$routes->get('administrator/events', 'View\EventController::index', ['filter' => 'auth:admin']);
$routes->get('administrator/events/create', 'View\EventController::create', ['filter' => 'auth:admin']);
$routes->post('administrator/events/create', 'View\EventController::create', ['filter' => 'auth:admin']);
$routes->match(['get', 'post'], 'administrator/events/edit/(:num)', 'View\EventController::edit/$1', ['filter' => 'auth:admin']);
$routes->post('administrator/events/delete/(:num)', 'View\EventController::delete/$1', ['filter' => 'auth:admin']);
$routes->post('payment/event_charges', 'View\EventController::eventUpdate', ['filter' => 'auth:update_invoice|view_financial_reports|administrator|administrative staff|principal,update']);
// Parent event participation
$routes->get('administrator/event-charges', 'View\EventController::eventShow');
$routes->get('administrator/event-charges/pdf', 'View\EventController::eventChargesPdf');
$routes->get('administrator/event-charges', 'View\EventController::eventShow', ['filter' => 'auth:view_invoice|view_financial_reports|administrator|administrative staff|principal']);
$routes->get('administrator/event-charges/pdf', 'View\EventController::eventChargesPdf', ['filter' => 'auth:view_invoice|view_financial_reports|administrator|administrative staff|principal']);
$routes->post('administrator/event-charges/remove/(:num)', 'View\EventController::removeCharge/$1', ['filter' => 'auth:update_invoice|view_financial_reports|administrator|administrative staff|principal,update']);
$routes->post('administrator/event-charges/payment/(:num)', 'View\EventController::toggleEventPayment/$1', ['filter' => 'auth:update_invoice|view_financial_reports|administrator|administrative staff|principal,update']);
$routes->post('administrator/event-charges/waiver/(:num)', 'View\EventController::toggleWaiverStatus/$1', ['filter' => 'auth:update_invoice|view_financial_reports|administrator|administrative staff|principal,update']);
$routes->get('administrator/get-students-with-charges', 'View\EventController::getStudentsWithCharges');
$routes->get('administrator/get-students-with-charges', 'View\EventController::getStudentsWithCharges', ['filter' => 'auth:view_invoice|view_financial_reports|administrator|administrative staff|principal']);
$routes->get('parent/events', 'View\ParentController::parentEventPage', ['filter' => 'auth:parent']);
// parent event participation page
$routes->post('parent/updateParticipation', 'View\ParentController::updateParticipation'); // handle parent participation updates
$routes->post('parent/updateParticipation', 'View\ParentController::updateParticipation', ['filter' => 'auth:parent']);
// Web View Routes for Invoices
$routes->get('invoices/getByParent/(:num)', 'View\InvoiceController::getByParent/$1');
$routes->get('invoices/create', 'View\InvoiceController::create');
$routes->get('invoices/getByParent/(:num)', 'View\InvoiceController::getByParent/$1', ['filter' => 'auth:parent|view_invoice|view_financial_reports|administrator|administrative staff|principal']);
$routes->get('invoices/create', 'View\InvoiceController::create', ['filter' => 'auth:create_invoice|view_financial_reports|administrator|administrative staff|principal,create']);
$routes->post('invoices/updateStatus/(:num)', 'View\InvoiceController::updateStatus/$1', ['filter' => 'auth:update_invoice|view_financial_reports|administrator|administrative staff|principal,update']);
// app/Config/Routes.php
@@ -639,8 +643,8 @@ $routes->group('admin', ['filter' => 'auth'], static function ($routes) {
$routes->group('admin', ['filter' => 'auth'], static function ($routes) {
$routes->get('broadcast-email', 'View\BroadcastEmailController::index');
$routes->post('broadcast-email/send', 'View\BroadcastEmailController::send');
$routes->post('broadcast-email/upload-image', 'View\BroadcastEmailController::uploadImage');
});
$routes->post('admin/broadcast-email/upload-image', 'View\BroadcastEmailController::uploadImage');
$routes->get('payment/financial_report', 'View\FinancialController::financialReport', ['filter' => 'auth:view_financial_reports|view_invoice|administrator|administrative staff|principal']);
@@ -651,7 +655,7 @@ $routes->get('payment/download_csv', 'View\FinancialController::downloadCsv', ['
$routes->get('administrator/tuition-forecast', 'View\TuitionForecastController::index', ['filter' => 'auth:view_financial_reports|view_invoice|administrator|administrative staff|principal']);
$routes->post('administrator/tuition-forecast/calculate', 'View\TuitionForecastController::calculate', ['filter' => 'auth:view_financial_reports|view_invoice|administrator|administrative staff|principal']);
$routes->get('administrator/tuition-forecast/export', 'View\TuitionForecastController::exportCsv', ['filter' => 'auth:view_financial_reports|view_invoice|administrator|administrative staff|principal']);
$routes->get('reports/downloadFinancialReport', 'View\FinancialController::downloadFinancialReport');
$routes->get('reports/downloadFinancialReport', 'View\FinancialController::downloadFinancialReport', ['filter' => 'auth:view_financial_reports|view_invoice|administrator|administrative staff|principal']);
// Financial APIs (JSON)
$routes->get('api/financial/report', 'View\FinancialController::financialReportData', ['filter' => 'auth']);
$routes->get('api/financial/summary', 'View\FinancialController::financialReportSummaryData', ['filter' => 'auth']);
@@ -685,20 +689,20 @@ $routes->get('reimbursements/export', 'View\ReimbursementController::export', ['
$routes->get('reimbursements', 'View\ReimbursementController::index', ['filter' => 'auth:view_financial_reports|administrator|administrative staff|principal']);
// Health check (upload dirs + DB timezone columns)
$routes->get('admin/health', 'View\HealthController::index');
$routes->get('admin/health', 'View\HealthController::index', ['filter' => 'auth:admin']);
//Notifications
$routes->get('notifications/active', 'View\NotificationsController::listActive');
$routes->get('api/notifications/active', 'View\NotificationsController::activeNotificationsData');
$routes->get('notifications/deleted', 'View\NotificationsController::listDeleted');
$routes->get('api/notifications/deleted', 'View\NotificationsController::deletedNotificationsData');
$routes->post('notifications/restore/(:num)', 'View\NotificationsController::restore/$1');
$routes->get('notifications/active', 'View\NotificationsController::listActive', ['filter' => 'auth:admin']);
$routes->get('api/notifications/active', 'View\NotificationsController::activeNotificationsData', ['filter' => 'auth:admin']);
$routes->get('notifications/deleted', 'View\NotificationsController::listDeleted', ['filter' => 'auth:admin']);
$routes->get('api/notifications/deleted', 'View\NotificationsController::deletedNotificationsData', ['filter' => 'auth:admin']);
$routes->post('notifications/restore/(:num)', 'View\NotificationsController::restore/$1', ['filter' => 'auth:admin']);
//$routes->post('notifications/restore/(:num)', 'View\NotificationsController::restore/$1');
//$routes->get('notifications/mark-read/(:num)', 'View\NotificationsController::markAsRead/$1');
$routes->get('/administrator/notifications_alerts', 'View\AdministratorController::notificationsAlerts');
$routes->post('/administrator/notifications_alerts/save', 'View\AdministratorController::saveNotificationSubjects');
$routes->get('/administrator/print-notifications', 'View\AdministratorController::printNotificationRecipients');
$routes->post('/administrator/print-notifications/save', 'View\AdministratorController::savePrintNotificationRecipients');
$routes->get('/administrator/notifications_alerts', 'View\AdministratorController::notificationsAlerts', ['filter' => 'auth:admin']);
$routes->post('/administrator/notifications_alerts/save', 'View\AdministratorController::saveNotificationSubjects', ['filter' => 'auth:admin']);
$routes->get('/administrator/print-notifications', 'View\AdministratorController::printNotificationRecipients', ['filter' => 'auth:admin']);
$routes->post('/administrator/print-notifications/save', 'View\AdministratorController::savePrintNotificationRecipients', ['filter' => 'auth:admin']);
$routes->get(
@@ -732,6 +736,8 @@ $routes->post(
['filter' => 'auth:create_invoice']
);
$routes->get('/parent/invoice_payment', 'View\InvoiceController::invoicePayment', ['filter' => 'auth:parent']); // Route for invoice payment page
$routes->get('/parent/financial-aid', 'View\ParentFinancialAidController::index', ['filter' => 'auth:parent']);
$routes->post('/parent/financial-aid', 'View\ParentFinancialAidController::submit', ['filter' => 'auth:parent']);
$routes->get('invoice/pay/(:num)', 'View\InvoiceController::payInvoice/$1', ['filter' => 'auth:view_invoice|view_payment|administrator|administrative staff|principal|parent']); // Route for paying the invoice
$routes->get('invoices', 'View\InvoiceController::index', ['filter' => 'auth:view_invoice|view_financial_reports|administrator|administrative staff|principal']); // Default route for invoices
$routes->get('invoices/(:any)', 'View\InvoiceController::index/$1', ['filter' => 'auth:view_invoice|view_financial_reports|administrator|administrative staff|principal']); // Route with school year filter
@@ -783,20 +789,20 @@ $routes->post('/principal/exam-drafts/upload-legacy', 'View\ExamDraftController:
* routes for View\MessagesController
* --------------------------------------------------------------------
*/
$routes->get('messages', 'View\MessagesController::index');
$routes->post('messages/send', 'View\MessagesController::send');
$routes->get('/messages/inbox', 'View\MessagesController::inbox');
$routes->get('/messages/sent', 'View\MessagesController::sent');
$routes->get('/messages/drafts', 'View\MessagesController::drafts');
$routes->get('/messages/trash', 'View\MessagesController::trash');
$routes->get('messages', 'View\MessagesController::index', ['filter' => 'auth']);
$routes->post('messages/send', 'View\MessagesController::send', ['filter' => 'auth']);
$routes->get('/messages/inbox', 'View\MessagesController::inbox', ['filter' => 'auth']);
$routes->get('/messages/sent', 'View\MessagesController::sent', ['filter' => 'auth']);
$routes->get('/messages/drafts', 'View\MessagesController::drafts', ['filter' => 'auth']);
$routes->get('/messages/trash', 'View\MessagesController::trash', ['filter' => 'auth']);
// Additional routes for handling actions like viewing, sending, deleting, etc.
$routes->get('/messages/view/(:num)', 'View\MessagesController::view/$1');
$routes->post('/messages/send', 'View\MessagesController::send');
$routes->get('/messages/delete/(:num)', 'View\MessagesController::delete/$1');
$routes->get('/messages/deletePermanent/(:num)', 'View\MessagesController::deletePermanent/$1');
$routes->get('/messages/restore/(:num)', 'View\MessagesController::restore/$1');
$routes->get('/messages/getRecipients/(:any)', 'View\MessagesController::getRecipients/$1');
$routes->get('/messages/view/(:num)', 'View\MessagesController::view/$1', ['filter' => 'auth']);
$routes->post('/messages/send', 'View\MessagesController::send', ['filter' => 'auth']);
$routes->get('/messages/delete/(:num)', 'View\MessagesController::delete/$1', ['filter' => 'auth']);
$routes->get('/messages/deletePermanent/(:num)', 'View\MessagesController::deletePermanent/$1', ['filter' => 'auth']);
$routes->get('/messages/restore/(:num)', 'View\MessagesController::restore/$1', ['filter' => 'auth']);
$routes->get('/messages/getRecipients/(:any)', 'View\MessagesController::getRecipients/$1', ['filter' => 'auth']);
/*
* --------------------------------------------------------------------
@@ -841,7 +847,7 @@ $routes->group('api/time', ['namespace' => 'App\Controllers\Api'], static functi
* routes for View\SchoolCalendarController
* --------------------------------------------------------------------
*/
$routes->group('administrator', ['namespace' => 'App\Controllers'], function ($routes) {
$routes->group('administrator', ['namespace' => 'App\Controllers', 'filter' => 'auth:admin'], function ($routes) {
$routes->get('calendar_view', 'View\SchoolCalendarController::index');
$routes->get('calendar_edit/(:num)', 'View\SchoolCalendarController::edit/$1');
$routes->get('calendar_delete/(:num)', 'View\SchoolCalendarController::delete/$1');
@@ -858,52 +864,52 @@ $routes->group('administrator', ['namespace' => 'App\Controllers'], function ($r
* routes for Parent Pages
* --------------------------------------------------------------------
*/
$routes->get('/parent/add_second_parent', 'View\ParentController::addSecondParent');
$routes->get('/parent/viewSecondParent', 'View\ParentController::viewSecondParent');
$routes->post('/parent/saveSecondParent', 'View\ParentController::saveSecondParent');
$routes->get('/parent/add_second_parent', 'View\ParentController::addSecondParent', ['filter' => 'auth:parent']);
$routes->get('/parent/viewSecondParent', 'View\ParentController::viewSecondParent', ['filter' => 'auth:parent']);
$routes->post('/parent/saveSecondParent', 'View\ParentController::saveSecondParent', ['filter' => 'auth:parent']);
$routes->get('/parent/enroll_classes', 'View\ParentController::enrollClasses');
$routes->post('/parent/enroll_classes_handler', 'View\ParentController::enrollClassesHandler');
$routes->get('/parent/enroll_success', 'View\ParentController::enrollSuccess');
$routes->get('/parent/enroll_failure', 'View\ParentController::enrollFailure');
$routes->get('/parent/payment', 'View\ParentController::viewPayments');
$routes->get('/parent/calendar', 'View\SchoolCalendarController::calendarParentView');
$routes->get('/parent/attendance', 'View\ParentController::attendance');
$routes->get('/parent/enroll_classes', 'View\ParentController::enrollClasses', ['filter' => 'auth:parent']);
$routes->post('/parent/enroll_classes_handler', 'View\ParentController::enrollClassesHandler', ['filter' => 'auth:parent']);
$routes->get('/parent/enroll_success', 'View\ParentController::enrollSuccess', ['filter' => 'auth:parent']);
$routes->get('/parent/enroll_failure', 'View\ParentController::enrollFailure', ['filter' => 'auth:parent']);
$routes->get('/parent/payment', 'View\ParentController::viewPayments', ['filter' => 'auth:parent']);
$routes->get('/parent/calendar', 'View\SchoolCalendarController::calendarParentView', ['filter' => 'auth:parent']);
$routes->get('/parent/attendance', 'View\ParentController::attendance', ['filter' => 'auth:parent']);
// Parent reporting: absence/late/early dismissal
$routes->get('parent/report-attendance', 'View\ParentAttendanceReportController::form');
$routes->post('parent/report-attendance', 'View\ParentAttendanceReportController::submit');
$routes->post('parent/report-attendance/update', 'View\ParentAttendanceReportController::update');
$routes->get('attendance/parent-reports', 'View\ParentAttendanceReportController::list');
$routes->get('parent/report-attendance', 'View\ParentAttendanceReportController::form', ['filter' => 'auth:parent']);
$routes->post('parent/report-attendance', 'View\ParentAttendanceReportController::submit', ['filter' => 'auth:parent']);
$routes->post('parent/report-attendance/update', 'View\ParentAttendanceReportController::update', ['filter' => 'auth:parent']);
$routes->get('attendance/parent-reports', 'View\ParentAttendanceReportController::list', ['filter' => 'auth:admin']);
// Admin/Teacher: early dismissal page by month
$routes->get('attendance/early-dismissals', 'View\ParentAttendanceReportController::earlyDismissals');
$routes->get('attendance/early-dismissals', 'View\ParentAttendanceReportController::earlyDismissals', ['filter' => 'auth:admin']);
// Admin/Teacher: add early dismissal
$routes->get('attendance/early-dismissals/new', 'View\ParentAttendanceReportController::addEarlyDismissalForm');
$routes->post('attendance/early-dismissals', 'View\ParentAttendanceReportController::saveEarlyDismissal');
$routes->post('attendance/early-dismissals/signature', 'View\ParentAttendanceReportController::uploadEarlyDismissalSignature');
$routes->get('attendance/early-dismissals/new', 'View\ParentAttendanceReportController::addEarlyDismissalForm', ['filter' => 'auth:admin']);
$routes->post('attendance/early-dismissals', 'View\ParentAttendanceReportController::saveEarlyDismissal', ['filter' => 'auth:admin']);
$routes->post('attendance/early-dismissals/signature', 'View\ParentAttendanceReportController::uploadEarlyDismissalSignature', ['filter' => 'auth:admin']);
// Parent report: client-side check API
$routes->post('api/parent/report-attendance/check', 'View\ParentAttendanceReportController::checkExisting');
$routes->post('api/parent/report-attendance/check', 'View\ParentAttendanceReportController::checkExisting', ['filter' => 'auth:parent']);
$routes->get('/support', 'View\StatsController::support');
$routes->get('no-kids', 'View\ParentController::noKids');
$routes->match(['get', 'post'], 'parent/edit-student/(:num)', 'View\ParentController::editStudent/$1');
$routes->get('parent/edit-all-students', 'View\ParentController::showEditAllStudentsModal');
$routes->post('parent/edit-all-students', 'View\ParentController::updateAllStudents');
$routes->get('no-kids', 'View\ParentController::noKids', ['filter' => 'auth:parent']);
$routes->match(['get', 'post'], 'parent/edit-student/(:num)', 'View\ParentController::editStudent/$1', ['filter' => 'auth:parent']);
$routes->get('parent/edit-all-students', 'View\ParentController::showEditAllStudentsModal', ['filter' => 'auth:parent']);
$routes->post('parent/edit-all-students', 'View\ParentController::updateAllStudents', ['filter' => 'auth:parent']);
// Show registration form with dynamic student and emergency contact blocks
$routes->get('/parent/register_student', 'View\ParentController::registerStudentForm');
$routes->get('/parent/child_register', 'View\ParentController::registerKidCheck');
$routes->get('/parent/register_student', 'View\ParentController::registerStudentForm', ['filter' => 'auth:parent']);
$routes->get('/parent/child_register', 'View\ParentController::registerKidCheck', ['filter' => 'auth:parent']);
// Handle form submission (students + emergency contacts)
$routes->post('/parent/register_student/save', 'View\ParentController::saveStudentRegistration');
$routes->post('/parent/update_student/(:num)', 'View\ParentController::updateStudent/$1');
$routes->get('/parent/edit_student/(:num)', 'View\ParentController::editStudent/$1');
$routes->post('/parent/edit_student/(:num)', 'View\ParentController::editStudent/$1');
$routes->post('/parent/delete_student/(:num)', 'View\ParentController::deleteStudent/$1');
$routes->post('/parent/register_student/save', 'View\ParentController::saveStudentRegistration', ['filter' => 'auth:parent']);
$routes->post('/parent/update_student/(:num)', 'View\ParentController::updateStudent/$1', ['filter' => 'auth:parent']);
$routes->get('/parent/edit_student/(:num)', 'View\ParentController::editStudent/$1', ['filter' => 'auth:parent']);
$routes->post('/parent/edit_student/(:num)', 'View\ParentController::editStudent/$1', ['filter' => 'auth:parent']);
$routes->post('/parent/delete_student/(:num)', 'View\ParentController::deleteStudent/$1', ['filter' => 'auth:parent']);
$routes->get('/parent/edit_emergency_contact/(:num)', 'View\ParentController::editEmergencyContact/$1');
$routes->post('/parent/edit_emergency_contact/(:num)', 'View\ParentController::editEmergencyContact/$1');
$routes->get('/parent/edit_emergency_contact/(:num)', 'View\ParentController::editEmergencyContact/$1', ['filter' => 'auth:parent']);
$routes->post('/parent/edit_emergency_contact/(:num)', 'View\ParentController::editEmergencyContact/$1', ['filter' => 'auth:parent']);
/*management navigation bar*/
@@ -915,7 +921,7 @@ $routes->post('nav-builder/reorder', 'View\NavBuilderController::reorder',
// Inventory routes
$routes->group('inventory', ['filter' => 'csrf'], static function ($routes) {
$routes->group('inventory', ['filter' => 'auth:view_inventory|administrator|administrative staff|principal'], static function ($routes) {
/** ---------------------------
* Movements (put FIRST)
@@ -1013,13 +1019,13 @@ $routes->group('communications', static function ($routes) {
////////////////////////////////////////////////
// app/Config/Routes.php
$routes->group('api', static function ($routes) {
$routes->group('api', ['filter' => 'auth:admin'], static function ($routes) {
// Families & Guardians API
$routes->get('students/(:num)/families', 'View\FamilyController::familiesByStudent/$1');
$routes->get('families/(:num)/guardians', 'View\FamilyController::guardiansByFamily/$1');
});
$routes->group('families', static function ($routes) {
$routes->group('families', ['filter' => 'auth:admin'], static function ($routes) {
// Allow GET for convenience in browser; keep POST for API/automation
$routes->match(['get', 'post'], 'bootstrap', 'View\FamilyController::bootstrap'); // protect with auth in production
$routes->post('attach-second-by-user', 'View\FamilyController::attachSecondByUser');
@@ -1031,10 +1037,10 @@ $routes->group('families', static function ($routes) {
$routes->post('unlink-student', 'View\FamilyController::unlinkStudent');
});
// Allow GET for manual triggering from browser
$routes->match(['get', 'post'], 'families/import-legacy', 'View\FamilyController::importSecondParentsFromLegacy');
$routes->match(['get', 'post'], 'families/import-legacy', 'View\FamilyController::importSecondParentsFromLegacy', ['filter' => 'auth:admin']);
// Admin page (protect with your auth/permission)
$routes->group('family', static function ($routes) {
$routes->group('family', ['filter' => 'auth:admin'], static function ($routes) {
$routes->get('', 'View\FamilyAdminController::index');
$routes->get('index', 'View\FamilyAdminController::index');
$routes->get('search', 'View\FamilyAdminController::search');
@@ -1043,13 +1049,13 @@ $routes->group('family', static function ($routes) {
$routes->post('compose-email/send', 'View\FamilyAdminController::sendComposeEmail');
});
// Convenience alias
$routes->get('family', 'View\FamilyAdminController::index');
$routes->get('family', 'View\FamilyAdminController::index', ['filter' => 'auth:admin']);
//////////////////////////////////////////////////////////
//upload files
$routes->get('receipts/(:any)', 'View\FilesController::receipt/$1', ['filter' => 'auth']);
$routes->get('reimbreceipts/(:any)', 'View\FilesController::reimb/$1', ['filter' => 'auth']); // serves from writable/uploads/reimbursements
$routes->get('early-dismissal-signatures/(:any)', 'View\FilesController::earlyDismissalSignature/$1');
$routes->get('early-dismissal-signatures/(:any)', 'View\FilesController::earlyDismissalSignature/$1', ['filter' => 'auth']);
// Expenses
$routes->get('expenses/edit/(:num)', 'View\ExpenseController::edit/$1', ['filter' => 'auth:view_financial_reports|administrator|administrative staff|principal']);
$routes->post('expenses/update/(:num)', 'View\ExpenseController::update/$1', ['filter' => 'auth:view_financial_reports|administrator|administrative staff|principal,update']);
@@ -1061,13 +1067,13 @@ $routes->post('reimbursements/update/(:num)', 'View\ReimbursementController::upd
// app/Config/Routes.php
$routes->get('whatsapp/', 'View\WhatsappController::index');
$routes->post('whatsapp/sendInvites', 'View\WhatsappController::sendInvites');
$routes->post('whatsapp/saveLink', 'View\WhatsappController::saveLink');
$routes->get('whatsapp/parent-contacts', 'View\WhatsappController::parentContacts');
$routes->get('whatsapp/parent-contacts-by-class', 'View\WhatsappController::parentContactsByClass');
$routes->get('whatsapp/', 'View\WhatsappController::index', ['filter' => 'auth:admin']);
$routes->post('whatsapp/sendInvites', 'View\WhatsappController::sendInvites', ['filter' => 'auth:admin']);
$routes->post('whatsapp/saveLink', 'View\WhatsappController::saveLink', ['filter' => 'auth:admin']);
$routes->get('whatsapp/parent-contacts', 'View\WhatsappController::parentContacts', ['filter' => 'auth:admin']);
$routes->get('whatsapp/parent-contacts-by-class', 'View\WhatsappController::parentContactsByClass', ['filter' => 'auth:admin']);
// Track WhatsApp group membership per class/parent
$routes->match(['get', 'post'], 'whatsapp/update-membership', 'View\WhatsappController::updateMembership');
$routes->match(['get', 'post'], 'whatsapp/update-membership', 'View\WhatsappController::updateMembership', ['filter' => 'auth:admin']);
@@ -1107,15 +1113,15 @@ $routes->post('admin/teacher-attendance/save-cell', 'View\AttendanceController::
$routes->post('admin/admins-attendance/save-cell', 'View\AttendanceController::saveCell');
$routes->get('parent/edit-emergency-contact', 'View\ParentController::editEmergencyContact');
$routes->match(['get', 'post'], 'parent/edit-emergency-contact/(:num)', 'View\ParentController::editEmergencyContact/$1');
$routes->get('parent/edit-emergency-contact', 'View\ParentController::editEmergencyContact', ['filter' => 'auth:parent']);
$routes->match(['get', 'post'], 'parent/edit-emergency-contact/(:num)', 'View\ParentController::editEmergencyContact/$1', ['filter' => 'auth:parent']);
$routes->get('rfid_coming_soon', 'View\RFIDController::rfidComingSoon');
$routes->post('/parent/save-emergency-contact', 'View\ParentController::saveEmergencyContact');
$routes->get('/parent/add-emergency-form', 'View\ParentController::addEmergencyForm');
$routes->post('/parent/save-emergency-contact', 'View\ParentController::saveEmergencyContact', ['filter' => 'auth:parent']);
$routes->get('/parent/add-emergency-form', 'View\ParentController::addEmergencyForm', ['filter' => 'auth:parent']);
$routes->get('report/combined', 'View\ScorePredictor::combinedReport');
@@ -1123,11 +1129,11 @@ $routes->get('report/combined', 'View\ScorePredictor::combinedReport');
//$routes->get('/parent/withdraw_success', 'View\ParentController::withdraw_success');
$routes->get('/profile/(:num)', 'View\ParentController::profile/$1');
$routes->post('/parent/updateProfile/(:num)', 'View\ParentController::updateProfile/$1');
$routes->get('/profile/(:num)', 'View\ParentController::profile/$1', ['filter' => 'auth']);
$routes->post('/parent/updateProfile/(:num)', 'View\ParentController::updateProfile/$1', ['filter' => 'auth']);
$routes->get('/preferences/(:num)', 'View\PreferencesController::index/$1');
$routes->post('/preferences/update/(:num)', 'View\PreferencesController::updatePreferences/$1');
$routes->get('/preferences/(:num)', 'View\PreferencesController::index/$1', ['filter' => 'auth']);
$routes->post('/preferences/update/(:num)', 'View\PreferencesController::updatePreferences/$1', ['filter' => 'auth']);
// Route to view_add_edit the configuration page
$routes->get('/configuration/configuration_view', 'View\ConfigurationController::index');
@@ -1248,7 +1254,7 @@ $routes->post('/register', 'View\RegisterController::register');
$routes->get('/register/success', 'View\RegisterController::success');
$routes->get('/parent/add-student-form', 'View\ParentController::addStudentForm');
$routes->get('/parent/add-student-form', 'View\ParentController::addStudentForm', ['filter' => 'auth:parent']);
$routes->get('/landing_page/admin_dashboard', 'View\LandingPageController::admin', ['filter' => 'auth:admin_dashboard,read']);
+32 -13
View File
@@ -70,21 +70,26 @@ class Services extends BaseService
$mail = new PHPMailer(true);
// Set up your PHPMailer configuration
$host = (string) env('MAIL_DEFAULT_HOST', env('SMTP_HOST', 'smtp.gmail.com'));
$user = (string) env('MAIL_DEFAULT_USER', env('SMTP_USER', ''));
$pass = (string) env('MAIL_DEFAULT_PASS', env('SMTP_PASS', ''));
$port = (int) env('MAIL_DEFAULT_PORT', env('SMTP_PORT', 465));
$encryption = strtolower((string) env('MAIL_DEFAULT_ENCRYPTION', env('SMTP_ENCRYPTION', 'ssl')));
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com'; // Your SMTP host
$mail->Host = $host;
$mail->SMTPAuth = true;
$mail->Username = 'alrahma.sunday.school@gmail.com'; // Your email
$mail->Password = 'psnp emdq dykw ypul'; // Your email password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mail->Port = 465;
$mail->Username = $user;
$mail->Password = $pass;
$mail->SMTPSecure = in_array($encryption, ['tls', 'starttls'], true)
? PHPMailer::ENCRYPTION_STARTTLS
: PHPMailer::ENCRYPTION_SMTPS;
$mail->Port = $port > 0 ? $port : 465;
$mail->Timeout = 10; // ⏱ 10-second timeout max
$mail->SMTPKeepAlive = false; // Prevent hanging connections
$mail->SMTPDebug = 0; // Set to 2 temporarily for debugging
$mail->SMTPDebug = 2; // You can set it to 1, 2, or 3 for increasing verbosity
$mail->Debugoutput = 'html'; // You can output it to 'html' or 'error_log'
$mail->Timeout = 10;
$mail->SMTPKeepAlive = false;
$mail->SMTPDebug = 0;
$mail->Debugoutput = 'error_log';
return $mail;
}
@@ -274,7 +279,6 @@ class Services extends BaseService
model(\App\Models\SchoolYearModel::class),
model(\App\Models\SchoolYearClosingBatchModel::class),
model(\App\Models\SchoolYearClosingItemModel::class),
model(\App\Models\ConfigurationModel::class),
static::schoolYearManagement(),
\Config\Database::connect()
);
@@ -301,4 +305,19 @@ class Services extends BaseService
static::emailService()
);
}
public static function financialAid(bool $getShared = true): \App\Services\FinancialAidService
{
if ($getShared) {
return static::getSharedInstance('financialAid');
}
return new \App\Services\FinancialAidService(
model(\App\Models\FinancialAidRequestModel::class),
model(\App\Models\InvoiceModel::class),
model(\App\Models\DiscountVoucherModel::class),
model(\App\Models\DiscountUsageModel::class),
new \App\Libraries\InvoiceLedgerService()
);
}
}
+9 -1
View File
@@ -32,7 +32,7 @@ class Session extends BaseConfig
*/
public string $cookieName = 'ci_session';
public string $cookieDomain = ''; // Leave blank for localhost
public bool $cookieSecure = false; // Set to false if not using HTTPS
public bool $cookieSecure = false; // Forced on in production via constructor
/**
* --------------------------------------------------------------------------
@@ -101,4 +101,12 @@ class Session extends BaseConfig
* DB Group for the database session.
*/
public ?string $DBGroup = null;
public function __construct()
{
parent::__construct();
$isProduction = ENVIRONMENT === 'production';
$this->cookieSecure = $isProduction;
$this->cookieName = $isProduction ? '__Host-ci_session' : 'ci_session';
}
}