Live demo · portfolio project
Helpdesk Ticketing System
IT support ticketing with roles, an audit trail and a responsive UI
An IT support app where staff raise requests and technicians resolve them, with role-based access, a full audit trail and a responsive interface.
The problem
IT requests arrive through chat, email and hallway conversations, so nobody knows what is open, who owns it or what changed. Staff can't see progress, and managers can't see the backlog.
What I built
Built the system in PHP and MySQL on CodeIgniter 3, with one record for every ticket. Access rules are enforced on the server, every status, priority and assignee change is written to an audit trail, and search and pagination keep large queues fast. The interface works on desktop and on tablets, with an off-canvas menu for smaller screens.
Outcome
A complete app with seeded data: sign-in, the ticket lifecycle, comments, role-based access, user administration and the audit trail. Access rules, CSRF protection, session handling and account lockout were checked in the browser and with HTTP-level tests.
Key features
- Role-based access for staff, technicians and admins
- Ticket lifecycle with status, priority, category and assignee
- Audit trail for every status, priority and assignee change
- Threaded comments on each ticket
- Search, filters, an open queue and an assigned-to-me view
- Admin user management with lockout safeguards
- Responsive layout with an off-canvas menu on smaller screens
Engineering highlights
- Access control on the server: every ticket and user screen checks the role and ownership. A staff member asking for someone else's ticket gets a 404, so ticket numbers can't be probed.
- Every status, priority and assignee change is saved together with its audit row, in one transaction, so the history can't drift from the data.
- A disabled account is locked out on its next request, not when its session expires.
- Safeguards for admins: they can't disable their own account or remove the last active admin.
- Search and pagination run in SQL, so large queues stay fast without loading every row.
- Strict Content Security Policy with no inline scripts, and database credentials read from environment variables.
Architecture
A CodeIgniter 3 front controller routes each request to an MVC controller. Every request re-checks the signed-in user against the database, and all data access goes through models to MySQL.
Client
- Browser (Bootstrap 5 UI)
Web
- Apache or PHP built-in server
- CodeIgniter 3 front controller
App
- Auth, ticket and user controllers
- Role guard and login check (MY_Controller)
- Models and audit trail
Data
- MySQL / MariaDB
- Database-backed sessions
- Sessions are stored in the database, and the session ID is regenerated on sign-in.
- Every form carries a CSRF token, and the Content Security Policy blocks inline scripts.
- Database credentials come from environment variables, not from the code.
Tech stack
- Back end
- PHP 8 on CodeIgniter 3 (MVC)
- Query Builder with parameterised queries
- Server-side form validation and CSRF protection
- Database-backed sessions with ID regeneration on sign-in
- bcrypt password hashing
- Data
- MySQL / MariaDB with foreign keys and indexes
- Audit trail table written in the same transaction as each change
- Idempotent schema and seed scripts
- Front end
- Bootstrap 5 with a custom design system
- Responsive layout with an off-canvas menu
- Vanilla JavaScript, no framework
- Security
- Content Security Policy and baseline security headers
- Role checks on the server, not only in the UI
- Generic sign-in errors, so accounts can't be enumerated