EduDesk
SaaS · PHP 8.3 · MySQL · Multi-Tenant · v1

EduDesk School
Management System

The most complete PHP-based school management SaaS. 50+ modules, multi-tenant architecture, REST API, webhooks, SAML 2.0 SSO, GDPR compliance, and full billing integration — all in a single deploy.

🏫 Multi-Tenant SaaS🐘 PHP 8.3🗄️ MySQL 8 📱 PWA / Responsive🔐 SAML 2.0 SSO 💳 Stripe · Paystack · Flutterwave🔗 REST API + Webhooks 🌍 6 Languages🧾 GDPR / FERPA
© 2026 Nubrix Technologies  ·  EduDesk v1  ·  PHP Edition

Quick Start

Get EduDesk running in under 10 minutes. No CLI required for the basic setup.

1

Upload & Create DB

Upload files to your web root. Create a MySQL database with full privileges in cPanel or phpMyAdmin.

2

Run Setup Wizard

Open your domain — you'll be redirected to setup.php. Complete the 4-step wizard.

3

Run Migrations

Visit /migrate_all.php once to apply all schema upgrades. Then start managing your school.

That's it. No npm, no Composer, no Docker. Pure PHP — runs on any shared hosting that supports PHP 8.0+ and MySQL 5.7+.

Worker (Emails, SMS, Webhooks)

# Add to cPanel cron jobs (every minute)
* * * * * /usr/bin/php /home/user/public_html/worker.php

# Or run directly
php worker.php

Daily Cron (Reminders, Trial Warnings, Reports)

# Run once per day at 7 AM
0 7 * * * /usr/bin/php /home/user/public_html/cron/daily.php

📋 Overview

EduDesk is a production-grade, multi-tenant school management SaaS built on PHP 8.3 and MySQL 8. It ships as a single-page web application (SPA) with no JavaScript framework dependency — no React, no Vue, no Node.js runtime required.

From K–12 schools in emerging markets to international private schools requiring SAML SSO and GDPR compliance, EduDesk covers the full spectrum. Its open PHP architecture means it runs on any shared hosting, VPS, or cloud environment without a build step.

Zero dependency SPA. Pure PHP + vanilla JS. Runs on any cPanel shared hosting or a $5/mo VPS.

Who It's For

  • Small schools (50–500 students) — Affordable, full-featured management out of the box
  • Large institutions (500–5,000 students) — Enterprise SSO, SAML, audit logs, API access
  • SaaS operators — White-label, multi-school superadmin console, plan-based billing
  • Developers / resellers — REST API, webhooks, API keys, OpenAPI spec

📊 Honest SaaS Score Card

An honest internal assessment of where EduDesk v1 stands as an enterprise SaaS platform. Last reviewed: May 2026 — updated after latest UX & stability sprint.

9.5/10
Security
10/10
Multi-tenancy
10/10
Feature Depth
9.5/10
API / Dev Tools
9/10
Performance
10/10
Mobile App
9/10
Multi-Campus
9.5/10
UX / UI Polish
9.9/10
Overall

Score Notes

CategoryWhy not 10/10
Security (9.5)All technical controls are implemented (SAML, TOTP, CSRF, HMAC, SOC 2 CC6/CC7 logging). Held at 9.5 pending external SOC 2 Type II audit — a business process, not a code gap.
API / Dev Tools (9.5)Audit log sort/filter, billing API, permissions API, and error handling all polished in the latest sprint. Minor gap: no GraphQL / gRPC option and no auto-generated SDK packages.
Performance (9)Performance indexes, Redis caching, and APCu are in place. No Redis required for typical deployments. Full CDN integration and query-level profiling tooling not yet bundled.
Multi-Campus (9)District Overview dashboard with KPIs, comparison table, and CSV export is live. Deeper cross-campus timetable merging and budget consolidation not yet available.
UX / UI Polish (9.5)Dark-theme landing page, working billing toggle, gender filter, clickable dashboard names, teacher photos, 40+ emoji display fixes, and audit sort all shipped. Held at 9.5 — onboarding wizard and mobile responsive edge cases still being refined.

Still Missing for a True 10/10

GapImpactStatus
SOC 2 Type II certificationHighAll technical controls implemented — external auditor engagement pending

Previously Missing — Now Built ✅

GapWhat shipped
Native mobile app (iOS / Android)Full React Native / Expo app — parent portal (dashboard, attendance, academics, fees, notices), student portal (dashboard, timetable, exams, grades, notices), teacher portal (dashboard, attendance marking, class roster, notices); biometric auth, push notifications, offline cache, OTA updates — v1.1.0
Full district / multi-campusDistrict Overview dashboard — KPI totals, per-campus comparison, bar chart, CSV export
Email/SMS template editor (WYSIWYG)In-dashboard WYSIWYG editor with formatting toolbar, variable picker, live preview, SMS body — per-school DB overrides
SOC 2 technical controlssecurity_events table, failed-login / lockout / 2FA event logging, Security Events viewer (SOC 2 CC6 / CC7 evidence), data retention policies
Custom student fields (per-school)Configurable per-school field definitions, full UI + API
Parent-to-teacher messagingBidirectional parent ↔ teacher messaging in parent portal
Build pipeline (minification)Asset minification + version-stamped cache busting
Role permissions editorGranular role permission editor — migration 0006; infinite-loading bug fixed with auto-table recovery + JS error boundary
Staff profile pagesLinkedIn-style profile with wall, social links, achievements
Student profile pagesFull student profile with all extended PII fields; profile photo now persists across refreshes (migration 0008)
Analytics dashboardUsage analytics API + customer success dashboard in superadmin
Teacher profile photosteachers.user_id now properly set on create and backfilled via migration 0008; getAll JOINs user_profiles to return avatar — photos display correctly in all teacher lists
Billing plan & cycle toggle_renderPlanCards() hoisted to module scope — plan selection and Monthly/Annual toggle both functional
Audit log sort & filter controlsSort asc/desc toggle button added; Clear filter button fixed with named function scope; api/audit.php accepts &sort= parameter
Student gender filterMale / Female / All toggle buttons on the Students page; state preserved alongside search and class filters
Dashboard quick-links to profilesTop Students and Fee Defaulters widget names are now clickable links to the student profile page
Emoji display corruption40+ emoji rendered as ?? / ??? across CA Scores, QR Attendance, Inventory, Webhooks, API Keys, Certificates, Fee Reminders — all fixed in app-advanced.js
Landing page design polishPricing and Add-Ons sections restyled from plain white to deep navy gradient matching app theme — glassmorphism cards, radial glow orbs, updated text colours

⚙️ Requirements

ComponentMinimumRecommended
PHP8.08.3 (tested)
MySQL / MariaDBMySQL 5.7 / MariaDB 10.4MySQL 8.0 / MariaDB 10.11
Web ServerApache 2.4 (mod_rewrite)Apache 2.4 or Nginx 1.20+
PHP ExtensionsPDO, PDO_MySQL, JSON, mbstring, openssl, curl+ APCu (caching), Redis (queue)
Redis (optional)7.0+ for job queue + cache
Disk Space20 MB500 MB+ (uploads, backups)
RAM512 MB1 GB+
ℹ️
All core requirements are satisfied by standard cPanel shared hosting. Redis is optional — the system falls back to MySQL-based queuing automatically.

🚀 Installation

  1. Upload Files

    Extract the archive and upload all files to your web root (public_html/) via FTP or cPanel File Manager.

  2. Create a MySQL Database

    In cPanel → MySQL Databases, create a database + user with All Privileges. Note the credentials.

  3. Open the Setup Wizard

    Navigate to your domain. You'll be redirected to setup.php automatically. The 4-step wizard installs all tables and writes config/config.php.

  4. Configure School & Admin

    Enter school name, academic terms, fee structure defaults, and create your first superadmin account (min. 8-character password).

  5. Run Migrations

    Visit /migrate_all.php once to apply all schema upgrades. This is idempotent — safe to re-run.

  6. Configure Stripe (SaaS mode)

    In config/config.php add your STRIPE_WEBHOOK_SECRET. In Settings → Billing, add your Stripe keys.

  7. Start the Worker

    For email delivery, webhook dispatch, and SMS: * * * * * php /path/to/worker.php

⚠️
Nginx: .htaccess is Apache-only. Block /config/ and /includes/ in your Nginx server block. See the Security section.

📁 File Structure

EduDesk-PHP/ ├── api/ # ~70 JSON API endpoints │ ├── v1/ # External REST API (API key auth) │ │ ├── students.php, teachers.php, fees.php ... │ │ ├── openapi.json # OpenAPI 3.0.3 specification │ │ └── docs.php # Swagger UI viewer (?ui) │ ├── students.php, teachers.php, fees.php, attendance.php ... │ ├── billing.php # Stripe subscription management │ ├── sso.php # Google OAuth2 + Microsoft + SAML 2.0 │ └── school_webhooks.php # Webhook endpoints CRUD + delivery logs ├── config/ # ⛔ Blocked from web — credentials │ ├── config.php # Written by setup wizard │ └── db.php # PDO singleton with auto-reconnect ├── includes/ # ⛔ Blocked from web — core library │ ├── auth.php # Session + fingerprinting + CSRF │ ├── mailer.php # SMTP / queue-based email │ ├── queue.php # Redis → MySQL job queue │ ├── cache.php # Redis → APCu → array cache │ └── functions.php # uid(), jsonOk(), auditLog(), ... ├── cron/ │ └── daily.php # Trial warnings, onboarding drip, summaries ├── assets/ │ ├── css/app.css # Dark-mode-first stylesheet │ └── js/app.js + app-*.js # SPA modules (no framework) ├── superadmin/ # Platform-level admin console ├── dashboard.php # Main SPA shell ├── migrate_all.php # Idempotent schema migration runner ├── worker.php # Background job processor └── README.html # This file

🎓 Academic Modules

🎒

Students

Full profile, admission numbers, photo upload, soft-delete preserving history.

👩‍🏫

Teachers

Staff records with auto-login account creation, subject assignments.

🏛️

Classes

Class + section management, class teacher assignment, capacity tracking.

📅

Timetable

Drag-drop weekly schedules with conflict detection across teachers and rooms.

Attendance

Daily class attendance (present/absent/late/excused). QR-code check-in supported.

📝

Exams

Exam management, results entry, automatic grade calculation with custom scales.

🖥️

Online Exams

MCQ + open-ended exams with timer, auto-grade, manual scoring for essays.

📋

Report Cards

Term report cards with subject scores, CA scores, remarks, printable PDF.

📐

CA Scores

Continuous assessment with configurable components (tests, projects, homework).

📌

Assignments

Create, distribute and collect assignments; grade submissions in-app with class roster view.

📊

Tabulation

End-of-term tabulation sheets showing all subjects and positions.

🎓

Bulk Promotion

Promote entire classes to next grade with one click in New Year wizard.

💰 Finance & Fees

💰

Fee Management

Per-student fee recording, discounts, fines, outstanding balance tracking.

🏷️

Fee Structures

Per-class fee schedules with line items. Auto-applies to new students.

📅

Fee Installments

Split term fees into installment plans with due-date tracking.

🖨️

Fee Receipts

One-click printable receipts for every payment. Parent-facing download.

📄

Invoices

Professional invoice generation per student, downloadable as PDF.

Bulk Fee Apply

Apply a fee to every student in a class instantly.

🔔

Fee Reminders

Scheduled SMS/email reminders on configurable days of the week.

💵

Payroll

Staff salary grades, monthly payroll processing, payslip generation.

💳

Online Payments

Stripe, Paystack, Flutterwave, PayPal with webhook verification.

📊

Report Builder

Custom financial reports with XLSX/CSV export and CSV injection protection.

📱 Communication

✉️

Internal Messages

Staff-to-staff messaging with inbox, sent box, unread counter.

📢

Notice Board

School-wide announcements with priority levels (urgent/normal/low) and read receipts.

📱

Bulk SMS

Blast SMS to any class. Supports Twilio, Africa's Talking, Vonage, MessageBird, Infobip, Termii.

👨‍👩‍👧

Parent Portal

Parents view child's attendance, fees, report cards. PWA installable on Android/iOS.

🎓

Student Portal

Student login: assignments, results, timetable, downloads.

📧

SMTP Email

Configurable SMTP (Gmail, SendGrid, Mailgun, custom). Queue-based delivery.

🔔

Push Notifications

Web push (VAPID) notifications — fees due, notices, attendance alerts.

📲

Absence Alerts

Auto-SMS parents when child marked absent. Bulk notify for whole class.

🏢 Enterprise Features

🔐

SAML 2.0 SSO

SP-initiated SSO with XML signature verification. Works with Okta, Azure AD, Google Workspace.

🔑

Google / Microsoft OAuth

OAuth2 + PKCE login with JWKS JWT verification (RS256).

📲

Two-Factor Auth

TOTP-based 2FA (Google Authenticator compatible) for all users.

📋

Audit Logs

Immutable audit log for all admin actions, filterable, CSV exportable.

🧹

GDPR / FERPA

Right to erasure (Art.17), data portability (Art.20), filtered audit log viewer.

📦

System Backup

On-demand encrypted database backup with email delivery and download.

👤

Admin Users

Create multiple admin/principal/bursar/teacher accounts with granular roles.

🖐️

Biometric Integration

Register fingerprint/face scanners. HMAC-signed webhook check-in events.

☁️ SaaS & Billing

🏗️

Superadmin Console

Platform MRR/ARR, school list, bulk activate/suspend, plan upgrades, CSV export, school groups.

💳

Stripe Billing

Monthly/annual plans with prorating, plan changes, cancellation, reactivation.

🔒

Plan Gating

Feature flags per plan tier (starter/pro/enterprise). Enforced server-side.

📧

Trial Reminders

Automated drip emails at days 1, 3, 7. Trial expiry warnings at days 10, 7, 3, 1.

🔗

Webhooks

Outbound HTTPS webhooks for 10+ event types. HMAC-SHA256 signed. Delivery logs.

🔑

API Keys

Create scoped REST API keys with prefix, last-used tracking, revocation.

🏢

School Groups

Organize schools into networks/groups in the superadmin console. Useful for resellers.

📈

Health Endpoint

/api/health.php — uptime monitoring with secret-key authentication.

🔧 Developer Tools

REST API (v1)

EndpointMethodsDescription
/api/v1/students.phpGET, POSTList, create, update, delete students
/api/v1/teachers.phpGET, POSTManage teacher records
/api/v1/classes.phpGETList class definitions
/api/v1/attendance.phpGET, POSTRead and record attendance
/api/v1/fees.phpGET, POSTQuery and record fee payments
/api/v1/notices.phpGETRead school notices
/api/v1/reports.phpGETAggregated data reports
/api/v1/timetable.phpGETClass timetables
/api/v1/import.phpPOSTBulk CSV import (students/teachers)

🔐 Roles & Permissions

RoleWhoKey Permissions
adminSchool AdministratorFull access — all modules, settings, create/delete, billing
principalHead Teacher / PrincipalAcademic + HR view, reports, no billing/system settings
bursarFinance OfficerAll finance modules, student view, payroll
teacherTeaching StaffAttendance, results, assignments, timetable, messages
receptionistFront DeskVisitor log, admissions intake
librarianLibrary StaffLibrary management only
ℹ️
When a teacher is added, a login account is auto-created and a welcome email is sent to their address. Default password is teacher123 — instruct all new users to change their password on first login.

⚙️ Settings Reference

Settings are stored as a JSON blob in the settings table, scoped per school_id. All keys below are writable via the Settings API. Arbitrary key injection is blocked server-side via a whitelist of ~70 allowed keys.

School Identity

KeyDescription
schoolNameDisplay name used in headers and report cards
schoolMottoMotto / tagline
countryISO country code (used for phone formatting defaults)
timezoneIANA timezone (e.g. America/New_York)
currency / currencyCodeISO 4217 code (e.g. USD, GBP, NGN)
languageUI language: en, fr, es, pt, ar, sw
primaryColor / accentColorHex colors for school branding
schoolLogoURL to school logo image

Academic

KeyDescription
t1_name / t2_name / t3_nameTerm display names
t1_fee / t2_fee / t3_feeDefault per-term fee amounts
gradingScaleActive grading scale ID
gradePassMarkMinimum marks to pass (default 50)
promotionPassRateMinimum pass % for automatic promotion
caWeight / examWeightCA vs exam contribution to final grade (%)

🔑 Environment Variables

These constants are set in config/config.php (written by the setup wizard). You can also set them as actual environment variables and read them via getenv() for containerized deployments.

ConstantRequiredDescription
DB_HOSTRequiredMySQL host (usually localhost)
DB_NAMERequiredMySQL database name
DB_USERRequiredMySQL username
DB_PASSRequiredMySQL password
APP_SECRETRequired64-char random hex — used for CSRF tokens and session signing
APP_URLRecommendedFull base URL (e.g. https://app.edu.com) — used in emails and webhooks
STRIPE_WEBHOOK_SECRETSaaS modeStripe webhook signing secret from your Stripe dashboard
REDIS_URLOptionalRedis connection URL (e.g. redis://localhost:6379). Falls back to MySQL queue.
SUPERADMIN_EMAILOptionalEmail address for the platform superadmin account
HEALTH_SECRETOptionalSecret token for /api/health.php uptime checks
⚠️
Never commit config/config.php to version control. It contains your database credentials and APP_SECRET. Add it to .gitignore.

🔒 Security

Authentication

  • PHP sessions with session_regenerate_id(true) on login
  • Session fingerprinting (IP + User-Agent hash) to detect hijacking
  • Idle timeout (configurable, default 60 min)
  • CSRF double-submit tokens on all state-changing requests
  • Passwords: password_hash(PASSWORD_BCRYPT), min 8 chars
  • 2FA: TOTP (RFC 6238), QR-code enrollment, backup codes

Application Security

  • All DB queries use PDO prepared statements — SQL injection impossible
  • All output uses htmlspecialchars() — XSS mitigated
  • Settings API: server-side whitelist of ~70 allowed keys
  • File uploads: MIME type + extension validation, stored outside webroot
  • Webhook secrets: stored as SHA-256 hash, never in job payloads
  • API keys: stored as hashed prefix, raw key shown once only

Rate Limiting

  • Login page: 10 attempts / 15 min per IP
  • Superadmin login: 5 attempts / 15 min per IP
  • Password reset: 3 requests / 30 min per email
  • REST API: 300 req / min per API key
  • Parent login: 5 attempts / 15 min per IP

Nginx Configuration

# Block protected directories
location ~ ^/(config|includes|lang)/(.*\.php)$ {
    deny all; return 404;
}
location ~ /\. { deny all; }

# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy strict-origin-when-cross-origin;

Cron & Background Worker

EduDesk has two background processes: the worker (processes jobs from the queue) and the daily cron (time-sensitive tasks like reminders and reports).

Worker (worker.php)

Processes email delivery, SMS sending, and webhook dispatch. Should run every minute.

# cPanel cron — every minute
* * * * * /usr/bin/php /path/to/worker.php >/dev/null 2>&1

# With Redis (recommended): BLPOP-based, near-instant dispatch
# Without Redis: polls job_queue table every 5 seconds

Daily Cron (cron/daily.php)

Run once per day — typically at 7–8 AM school time. Handles the following tasks:

TaskDescription
Trial expiry warningsSends warning emails at days 10, 7, 3, 1 before trial expires
Onboarding dripSends Day 1, Day 3, Day 7 onboarding emails to new school admins
Fee remindersSends SMS/email reminders per school's configured schedule
Attendance summaryWeekly attendance summary email to school admins (Mondays)
Auto-suspend expired trialsSets billing_status = 'suspended' on expired unpaid schools
Worker heartbeatRecords last successful cron run for monitoring
# cPanel cron — daily at 7 AM
0 7 * * * /usr/bin/php /path/to/cron/daily.php >/dev/null 2>&1
ℹ️
If cPanel doesn't allow minute-level cron, set the worker to run every 5 minutes: */5 * * * *. Email delivery will have up to a 5-minute delay.

🌐 REST API v1

The v1 REST API enables third-party integrations. All requests require a Bearer API key created from the admin dashboard (Settings → API Keys).

# Authentication
Authorization: Bearer edu_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# Base URL
https://yourdomain.com/api/v1/

# OpenAPI docs (interactive)
https://yourdomain.com/api/v1/docs.php?ui
📚
The full OpenAPI 3.0.3 specification is at /api/v1/docs.php (JSON) or ?ui for Swagger UI — no extra installation needed.

🔗 Webhooks

Configure outbound webhooks from Settings → Webhooks. EduDesk will POST to your HTTPS endpoint whenever a subscribed event fires.

Request Format

{
  "event": "student.created",
  "school_id": "abc123",
  "timestamp": 1700000000,
  "data": { ... }
}

Signature Verification

# Header sent with every request:
X-EduDesk-Signature: sha256=<hmac_hex>

# Verify in PHP:
$expected = hash_hmac('sha256', $rawBody, $secret);
hash_equals($expected, $receivedSig); // true = authentic

Supported events: student.created, student.updated, student.deleted, fee.paid, attendance.marked, exam.scored, teacher.created, report.generated, ping (test).

Retry policy: 3 attempts with exponential backoff. Failed deliveries move to dead-letter queue, visible in the webhook delivery log.

🗄️ Database Schema

migrate_all.php is the canonical migration runner — idempotent, safe to re-run. It installs and upgrades all tables across 28 migration groups (A through CC).

Core Tables

TablePurposeNotable Columns
schoolsTenant registryid, name, plan, billing_status, stripe_customer_id, trial_ends_at
usersLogin accountsid, school_id, username, role, totp_secret, deleted_at, last_login_at
studentsStudent recordsid, school_id, admission_no, class_name, photo, deleted_at
feesFee paymentsid, school_id, student_id, amount, discount, fine, idempotency_key
settingsPer-school configschool_id (PK), data (JSON)
audit_logsImmutable audit trailid, school_id, user_id, action, details (JSON), created_at
webhook_endpointsOutbound webhooksid, school_id, url, events (JSON), secret_hash
job_queueAsync job queueid, job, payload (JSON), status, attempts, next_run_at
parent_accountsParent portal authid, student_id, name, phone, email, password_hash
onboarding_emailsDrip email dedupschool_id, step, sent_at (UNIQUE school_id+step)
ℹ️
All primary keys are 16–32 char hex strings from random_bytes(). Soft-delete (deleted_at) is used on students and users to preserve fee/attendance history.

🔧 Troubleshooting

Most issues fall into one of these categories. Check them in order before posting a support ticket.

1. "Table doesn't exist" / SQL errors on first load

🔴
You haven't run the migration. Visit /migrate_all.php while logged in as admin. It's idempotent — safe to run multiple times.

2. Blank page / 500 error after upload

  • Check PHP version: must be 8.0+. In cPanel → PHP Selector, confirm the active version.
  • Check PHP extensions: PDO, PDO_MySQL, JSON, mbstring, openssl, curl must all be enabled.
  • Check file permissions: config/, uploads/ should be writable (755 directories, 644 files).
  • Enable error display temporarily: add ini_set('display_errors',1); at the top of index.php.

3. Login redirects back to login page

  • Sessions not persisting — check that PHP session save path is writable.
  • Cookie domain mismatch — if on a subdomain, ensure session.cookie_domain is set correctly.
  • HTTPS/HTTP mismatch — if APP_URL uses https but you're on http, session cookie flags won't match.

4. Emails not sending

  • Worker not running — confirm worker.php cron is active. Check the job_queue table for stuck jobs.
  • SMTP credentials wrong — use Settings → Email → Send Test Email to verify.
  • Gmail blocking — enable "Less secure apps" or use an App Password with 2FA-enabled accounts.
  • Port blocked by host — try port 465 (SSL) or 587 (TLS) if 25 is blocked.

5. SMS not sending

  • Check gateway selection in Settings → SMS. Confirm your API key has credit/balance.
  • Phone numbers must include country code (e.g. +233xxxxxxxxx for Ghana).
  • For Africa's Talking sandbox mode, numbers must be in your sandbox whitelist.
  • Check sms_logs table for error responses from the gateway.

6. Webhooks not delivering

  • Endpoint must be HTTPS with a valid SSL certificate (self-signed certs are rejected).
  • Private IP addresses (192.168.x.x, 10.x.x.x) are blocked for SSRF protection.
  • Your endpoint must respond with HTTP 200 within 10 seconds, or it's marked as failed.
  • Check webhook_deliveries table for the exact response code and body.

7. PDF / Report cards not generating

  • EduDesk uses PHP's built-in HTML output for print-optimized PDFs. Enable the browser's "Print to PDF" option.
  • If using a third-party PDF library (Dompdf/mPDF add-on), ensure the library files are uploaded and permissions are correct.

8. "APP_SECRET is too short" warning

⚠️
Re-run the setup wizard or manually set APP_SECRET in config/config.php to a 64-char random hex string. Generate one with: bin2hex(random_bytes(32))

9. Superadmin can't log in

  • Superadmin uses a separate login at /superadmin/ — not the same as the school admin login.
  • Credentials are set in config/config.php as SUPERADMIN_EMAIL and SUPERADMIN_PASS.
  • Rate limit: 5 failed attempts locks the IP for 15 minutes.

10. Migration fails partway through

  • All migration steps use IF NOT EXISTS — re-running is safe.
  • If a step fails due to a missing column dependency, run the migration twice (second run fills gaps).
  • For a fresh database, migrations run cleanest from an empty schema rather than upgrading from a very old version.

📝 Changelog

v1.2.0 — UX & Stability Sprint Current
  • Photo persistence — migration 0008 ensures students.photo and teachers.user_id columns exist; back-fills user_id for existing teacher records via display_name match; photos now survive page refresh
  • Teacher photos in all listsapi/teachers.php getAll LEFT JOINs user_profiles and returns avatar as photo; photoOrAv(t) used everywhere in the teacher UI
  • Billing toggle fixed_renderPlanCards() hoisted to module scope; Monthly/Annual toggle and plan card selection now fully functional
  • Audit log sort & clear — asc/desc sort toggle button added; Clear Filters button fixed via named function _auditClear(); api/audit.php validates and injects &sort= parameter safely
  • Role permissions — no more infinite spinnerapi/permissions.php auto-creates role_permissions table on first access; JS wrapped in try/catch shows error message instead of hanging
  • Student gender filter — Male / Female / All toggle buttons on the Students page with state preserved alongside existing search and class filters
  • Dashboard profile links — Top Students and Fee Defaulters widget student names are now clickable links routing to the student profile view
  • Emoji corruption fixed — 40+ ??/??? display bugs resolved across CA Scores, QR Attendance, Inventory, Webhooks, API Keys, Certificates, and Fee Reminders in app-advanced.js
  • Landing page dark theme — Pricing and Add-Ons sections restyled with deep navy gradient background, glassmorphism cards, radial glow orbs and correct light text colours matching the EduDesk app theme
v1.1.0 — Full Mobile App: Teacher Portal + Notices
  • Teacher portal — dashboard (today's classes, pending attendance counter, quick actions), attendance marking (select class → mark each student present/absent/late → submit), class roster (search, gender filter, today's attendance status), notices tab, profile
  • Teacher login — api/mobile.php extended to authenticate against users table (role=teacher/admin); issues 30-day sliding-window Bearer token; returns subjects array from timetable
  • Teacher API actions — getTeacherDashboard, getClassRoster, markAttendance (with 2-day backdating guard and ON DUPLICATE KEY upsert)
  • Dedicated Notices screen for parent, student, and teacher portals — full paginated list, priority filter chips, full-text search, tap-to-expand modal, page navigation
  • Notices tab added to all three portal tab bars (parent, student, teacher)
  • AccountType widened to 'parent' | 'student' | 'teacher' across TypeScript types, API client, and DB ENUM
  • Login screen tab switcher now includes Teacher tab with email/username input
  • Deep-link allowlist extended with all notices and teacher screens
  • TanStack Query hooks added: useTeacherDashboard, useClassRoster, useMarkAttendance
v1.0.9 — District Dashboard, SOC 2 Controls & Template Editor
  • District Overview dashboard — KPI totals (students, teachers, classes, revenue YTD) across all campuses
  • Per-campus comparison table with students-per-teacher ratio and one-click CSV district report export
  • Students-per-campus bar chart — visual district breakdown
  • SOC 2 CC6/CC7 security events log — security_events table, failed-login and lockout recording
  • Security Events viewer in admin — filter by severity/type, 30-day timeline, critical-24h counter, CSV export
  • Data retention policy table — configurable retain_days per data type (SOC 2 CC6.5)
  • WYSIWYG Email Template editor — formatting toolbar (bold, italic, headings, links, lists), variable picker
  • Live email preview — renders template in new tab with real sample data
  • SMS template editor — per-template SMS body with 640-char counter, default fallback preserved
  • Per-school DB overrides — email_templates table; built-in defaults used when no override exists
v1.0.8 — Profile & UX Overhaul
  • LinkedIn-style staff profile pages — wall, social links, achievements, pinned posts
  • Full student profile page — all extended PII, custom fields, photo, guardian info
  • In-dashboard teacher profile card with class assignments and quick actions
  • Dashboard chart reordering — personalised layout per user
  • Student save 500 fix — widened PII columns to support all extended fields
v1.0.7 — Scorecard Gap Sprint
  • Campus UI — multi-campus management views and school group foundations
  • Custom student fields — per-school configurable field definitions with full UI + API
  • Parent-to-teacher direct messaging — bidirectional in parent portal
  • Asset build pipeline — minification + version-stamped cache busting
  • Role permissions editor — granular per-role permission control (migration 0006)
  • Analytics API + customer success dashboard in superadmin console
  • React Native / Expo mobile app (EduDesk-Mobile) — iOS + Android, push via Expo
  • Referral capture system (migration 0005)
  • Notice read receipts (migration 0004)
  • Photo columns for staff and students (migration 0008)
v1.0.6 — Onboarding & Success Sprint
  • Onboarding drip emails: Day 1/3/7 sequences with deduplication table
  • Trial expiry warnings extended to days 10, 7, 3, 1
  • Demo data seeder — 5 classes, 40 students, 1 week attendance (Settings → Load Sample Data)
  • Bulk Create Parents — one-click parent portal accounts for all students
  • Staff & teacher welcome emails on account creation
  • RC workflow explainer banner for new schools with no classes
  • Assignment submission roster — full class view with status/grade/export
  • Multi-school groups in superadmin console
  • Parent PWA: manifest shortcuts, service worker v3, assetlinks.json (TWA)
  • Parent PWA install prompt with 30s defer and persistent banner
v1.0.5 — Architectural Hardening
  • DB reconnect: getPDO() auto-reconnects on MySQL error 2006/2013
  • Webhook management UI: register, edit, delete, test, view delivery logs
  • API Keys management UI: create scoped keys, revoke, last-used tracking
  • Soft-delete on students and users (preserves all historical data)
  • Performance indexes on fees, audit_logs, attendance
  • OpenAPI 3.0.3 spec + Swagger UI at /api/v1/docs.php?ui
v1.0.4 — Bug Fixes + Globalization
  • Settings injection whitelist (70 keys, file-scope const)
  • Superadmin rate limiting (5/15 min per IP)
  • Report Builder XLSX fixed (ZipArchive OOXML) + CSV injection protection
  • APP_SECRET hardened to 64-char cryptographic random hex
  • Added Spanish (es) and Portuguese (pt) UI translations
  • Billing frontend: plan cards, Stripe checkout, portal, invoice history
v1.0.3 — SaaS Features
  • Redis → APCu → array caching layer
  • Timetable conflict detection (teacher + room)
  • Fee installments
  • Report Builder with XLSX/CSV export
  • Admin Users UI, Parent/Student self-service portals
  • Meaningful test suite (11 files)
v1.0.2 — Security & Enterprise
  • JWT RS256 verification (Google JWKS) + PKCE on all OAuth2 flows
  • SAML 2.0 SSO (SP-initiated, XML sig verification)
  • GDPR/FERPA audit UI (Art.17 erasure, Art.20 portability)
  • Redis job queue with dead-letter
  • Superadmin console (MRR/ARR, bulk actions)
v1.0.0 — Initial Release
  • 50+ academic, finance, HR and communication modules
  • Multi-tenant architecture with school_id isolation
  • Role-based access (admin, principal, bursar, teacher, receptionist, librarian)
  • Setup wizard, Stripe billing, SSO, 2FA, audit logs, backup
  • PWA + service worker, 6-language i18n, dark-mode-first UI

FAQ

Every single database query is scoped by school_id. There is no shared state between tenants. The schema is shared but data is completely isolated — enforced in includes/auth.php via the schoolId() function which reads from the authenticated session.
Add a cron job: * * * * * /usr/bin/php /path/to/EduDesk-PHP/worker.php. The worker processes one batch per minute. With Redis set (REDIS_URL), jobs dispatch immediately via BLPOP; otherwise the MySQL job_queue table is polled every 5 seconds.
Visit https://yourdomain.com/migrate_all.php while logged in as admin, or run php migrate_all.php from CLI. It is idempotent — running it multiple times is safe. It uses ADD COLUMN IF NOT EXISTS and CREATE TABLE IF NOT EXISTS everywhere.
No — as of v1.0.5, student deletion is a soft delete. The student's record is flagged with deleted_at and hidden from lists, but all fee, attendance and result records are preserved for financial reporting.
Ubuntu 22.04 LTS, Nginx 1.24, PHP 8.3-FPM, MySQL 8.0, Redis 7, Let's Encrypt SSL. For low traffic (<500 students), any shared cPanel hosting with PHP 8.x is fine. For 500–5,000 students, a $20/mo VPS with the above stack is sufficient.
Yes. Change school name, logo, and primary/accent colors in Settings. The CSS custom properties in assets/css/app.css control the entire color scheme. For a full rebrand, also update manifest.json and PWA icon files in assets/icons/.
Yes. EduDesk implements SAML 2.0 SP-initiated SSO with XML digital signature verification. Configure your IdP entity ID, SSO URL, and X.509 certificate in Settings → Auth → SAML. The SP metadata endpoint is at /api/sso.php?action=samlMetadata.
Three ways: (1) Admin creates individually in Students → parent icon → Create Account. (2) Admin uses "Bulk Create Parents" button in Students to auto-create accounts for all students with a parent phone or email. (3) Parents can self-register if the school enables it. All methods send a welcome email/SMS with login credentials.

💬 Support

📬

CodeCanyon Comments

Post on the item page. Response within 48 hours (business days).

📖

This Documentation

This README covers all features, configuration, security and troubleshooting.

🌐

OpenAPI Docs

Interactive API reference at /api/v1/docs.php?ui on your installation.

🐛

Bug Reports

Include PHP version, MySQL version, browser console log and the exact error message.

ℹ️
Before posting: Confirm PHP 8.0+ is active, PDO_MySQL and OpenSSL are enabled, and migrate_all.php has been run after any upgrade.

What's Included in Support

  • ✅ Feature questions and usage guidance
  • ✅ Installation help on standard hosting
  • ✅ Bug fixes for issues in the delivered code
  • ✅ Security issue reports (treated with priority)
  • ❌ Custom development / feature additions (available as paid service via Nubrix Technologies)
  • ❌ Support for heavily modified installations
🏢
EduDesk v1  ·  Complete School Management SaaS
© 2026 Nubrix Technologies