A full-stack Helpdesk Ticket system built with FastAPI, SQLModel, SQLite, and vanilla HTML/CSS/JavaScript.
This project demonstrates:
- RESTful CRUD API design
- JWT-based authentication
- Dependency injection with FastAPI
- Secure per-user ownership enforcement
- Query filtering & pagination
- Clean frontend ↔ backend integration
- Automated testing with pytest
- User registration with unique username enforcement
- Password hashing using
bcrypt - Login returns a signed JWT access token
- Token expiration support
- Protected routes require
Authorization: Bearer <token> - Signature + expiration validation
- Secure ticket ownership enforcement
Authenticated users can:
- Create tickets
- View all their tickets
- Search tickets with query parameters
- Update tickets (partial PATCH)
- Delete tickets
All ticket queries enforce:
- Ticket must exist
- Ticket must belong to the authenticated user
Supports filtering by:
title(partial match)description(partial match)priority(1–5)status(open | in_progress | closed)offsetlimit(max 100)
Example: /api/tickets/search?title=printer&priority=3&limit=5
PATCH requests:
- Only update explicitly provided fields
- Ignore
nullvalues - Reject empty update payloads
Prevents accidental overwriting of required database fields.
- SQLite
- SQLModel ORM
- Dependency-injected sessions
- Automatic table creation on startup
- Unique constraint on usernames
Includes pytest tests covering:
- Ticket creation
- Ownership enforcement
- Update & delete behavior
- Authentication requirements
Backend
- FastAPI
- SQLModel
- SQLite
- Passlib (bcrypt)
- python-jose (JWT)
Frontend
- HTML
- CSS
- Vanilla JavaScript
fetch()API- Session storage for JWT
Testing
- pytest
- TestClient
helpdesk-api/
│
├── app/
│ ├── main.py
│ ├── db.py
│ ├── models.py
│ ├── auth.py
│ └── tickets.py
│
├── static/
│ ├── css/
│ ├── js/
│ ├── index.html
│ ├── tickets.html
│ ├── add_ticket.html
│ ├── update_ticket.html
│ ├── delete_ticket.html
│ ├── login.html
│ └── register.html
│
├── tests/
│ ├── conftest.py
│ └── test_tickets.py
│
├── requirements.txt
├── .env
├── .gitignore
└── database.db
- User registers → password hashed with bcrypt
- User logs in → server returns JWT
- JWT stored in
sessionStorage fetch()helper automatically attachesAuthorizationheader- Backend dependency validates:
- Token exists
- Signature is valid
- Token is not expired
- Payload contains required claims
- Centralized API helper (
requestOrThrow) - Automatic JWT header injection
- Centralized error extraction
- Form validation before API calls
- Redirect flow after successful operations
- Dynamic auth UI (shows logged-in user)
git clone <your-repo-url>
cd helpdesk-apipython -m venv .venvActivate it:
Windows
.venv\Scripts\activatemacOS/Linux
source .venv/bin/activatepip install -r requirements.txtCreate a .env file in the project root:
SECRET_KEY=your_super_secret_key_hereSECRET_KEY.
uvicorn app.main:app --reloadVisit:
OpenAPI docs:
-
Go to the home page:
http://127.0.0.1:8000/ -
Register a user:
/static/register.html
-
Login:
/static/login.html
-
Create / view / search / update / delete tickets from the navbar links.
The frontend uses a shared request helper to:
- attach your JWT automatically to API requests
- extract FastAPI error messages cleanly
- Passwords are stored only as bcrypt hashes (never plaintext).
- JWT tokens are signed and validated on every protected request.
- Ticket ownership is enforced in database queries (user_id must match).
- PATCH updates ignore
nullvalues and reject empty payloads to prevent accidental overwrites.
python -m pytest
Educational / portfolio project.