A full-stack user management system built with Docker, Nginx, PHP, MySQL, and a React + Vite frontend.
This project demonstrates a complete authentication flow that includes registration, email verification, login, logout, password reset, user actions, and admin actions.
- Features
- Tech Stack
- Project Structure
- Setup
- Environment Configuration
- Database
- API Endpoints
- API Documentation
- Notes
- Useful Files
- Contribution
| Feature | Description |
|---|---|
| Role-based access | Supports admin and user roles |
| Registration | Validation with username, email, and password rules, plus secure password hashing |
| Email verification | Mock mail delivery with hashed verification tokens and link-based verification |
| Login | JWT access token + HttpOnly refresh token cookie on success |
| Logout | Clears refresh token and returns user to login flow |
| Password reset | Token generation, mock mail delivery, and password update flow |
| Auth-protected actions | Access token required for protected user endpoints |
| Admin actions | Role verification for admin-only endpoints |
| API delivery | Backend served through Nginx and PHP-FPM |
| Frontend delivery | React app served by Nginx |
| Technology | Purpose |
|---|---|
| Docker | Containerized deployment for frontend, backend, and database |
| Nginx | Reverse proxy for API and static hosting for frontend |
| PHP 8.4 FPM | Backend API server |
| MySQL | Application database |
| React + Vite | Frontend UI and client application |
| JWT | Access token authentication |
app/– frontend React applicationapi/– PHP backend API and authentication logicdatabase/– MySQL initialization SQLcompose.yaml– Docker services for frontend, backend, Nginx, and database
- Docker
- Docker Compose
From the repository root:
docker compose up -d --build- Frontend:
http://localhost:5173 - Backend API:
http://localhost:8080
The backend reads variables from api/.env.
If the file is missing, create it with values similar to:
MYSQL_HOST=db
MYSQL_DB_NAME=user_management_system
MYSQL_USERNAME=user
MYSQL_PASS=1234
CLIENT_URL=http://localhost:5173
JWT_SECRET=your_jwt_secret_here
DEV=true
STATIC_ADMIN_ID=1The frontend uses app/.env with:
VITE_AUTH_API_BASE_URL=http://localhost:8080/api/v1/authThe MySQL service initializes schema from database/init.sql.
It creates the following tables:
accountspassword_resetsemail_verificationsinboxrefresh_tokens
The backend routes are defined under /api/v1/auth.
POST /api/v1/auth/registerPOST /api/v1/auth/loginPOST /api/v1/auth/logoutGET /api/v1/auth/login/refresh-token
POST /api/v1/auth/email/verify-requestPOST /api/v1/auth/email/verified
POST /api/v1/auth/password/forgetPOST /api/v1/auth/password/reset
GET /api/v1/auth/inboxPATCH /api/v1/auth/inbox/mark-as-read/{id}
GET /api/v1/auth/user/fetch-userPATCH /api/v1/auth/user/change-username
GET /api/v1/auth/admin/fetch-all-usersPATCH /api/v1/auth/admin/edit-user-info
- Root docs:
http://localhost:8080/ - API docs:
http://localhost:8080/api
- Email sending is simulated via the mock mail interface.
- Registration enforces:
- username length ≥ 3
- fake email domain for PDPA safety
- password length ≥ 8
- Passwords are hashed before being saved to the database.
- Verification and password-reset tokens are hashed and stored in the database.
- Login success sets an HttpOnly refresh cookie and returns a JWT access token to the client.
api/auth/docs_endpoints.php— API endpoint reference dataapi/Dockerfile— backend PHP serviceapp/Dockerfile— frontend build and Nginx deploymentapi/nginx.conf— backend Nginx configdatabase/init.sql— initial database schema
Feel free to extend the project with:
- real email delivery
- admin dashboard enhancements
- improved validation and security hardening
- production-ready Docker networking and secrets management