A REST API ticket system built in Go with JWT authentication, ownership-based access control, and in-memory storage.
- Go 1.21
- gorilla/mux — routing
- golang-jwt/jwt — JWT auth
- bcrypt — password hashing
- In-memory store (thread-safe via
sync.RWMutex)
git clone https://github.com/faheem2312/Ticket-System.git
cd Ticket-System
copy .env.example .env # Windows
# cp .env.example .env # Mac/Linux
go mod tidy
go run ./cmd/main.goServer runs on http://localhost:8080.
docker build -t ticket-system .
docker run -p 8080:8080 -e JWT_SECRET=your-secret ticket-systemcurl http://localhost:8080/health
# {"status":"ok"}| URL | |
|---|---|
| App | https://ticket-system-k8ek.onrender.com |
| Health check | https://ticket-system-k8ek.onrender.com/health |
Note: Render free tier spins down after inactivity. First request may take ~30 seconds to wake up.
{"email": "user@example.com", "password": "secret123"}Response 201:
{"id": "...", "email": "user@example.com", "created_at": "..."}{"email": "user@example.com", "password": "secret123"}Response 200:
{"token": "<jwt>"}All ticket endpoints require the header:
Authorization: Bearer <token>
{"title": "Bug in login", "description": "Users can't log in"}{"status": "in_progress"}Status flow: open → in_progress → closed
Closed tickets cannot be reopened.
go test ./...- Storage is in-memory; data resets on restart.
- JWT tokens expire after 24 hours.
JWT_SECRETdefaults to a placeholder if not set — always override in production via environment variable.- Ownership: users can only view/update their own tickets. Other users' tickets return
404(not403) to avoid leaking ticket existence. - Email is normalized (lowercased, trimmed) on register and login.