Form Validation: - Create comprehensive Zod validation schemas for all forms - Login form: email, password validation - Register form: first name, last name, email, password strength requirements - Profile update form: all user fields with optional phone/address - Password change form: current password, new password confirmation - Vote submission form: election ID and candidate selection Password Strength: - Minimum 8 characters - At least one uppercase letter - At least one digit - At least one special character (!@#$%^&*) React Hook Form Integration: - Update login page with useForm and field-level error display - Update register page with form validation and error messages - Show validation errors inline with red borders - Disable form submission while loading or submitting - Better user feedback with detailed error messages Type Safety: - Zod schemas with TypeScript inference - Type-safe form data types - Proper error handling and validation Build Status: - All pages compile successfully - Zero TypeScript errors - Bundle size includes Zod (~40 kB) and React Hook Form - Login/Register pages: 145 kB First Load JS (includes new validation libraries) - Shared bundle remains ~102 kB Setup: - npm install zod react-hook-form @hookform/resolvers - Ready for production with form validation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
445 lines
10 KiB
Markdown
445 lines
10 KiB
Markdown
# E-Voting System - Backend & Frontend Integration Setup
|
|
|
|
This guide explains how to run both the FastAPI backend and Next.js frontend together.
|
|
|
|
## System Requirements
|
|
|
|
- Python 3.12+
|
|
- Node.js 18+ (for npm)
|
|
- MySQL 8.0+ (or SQLite for development)
|
|
- Poetry (for Python dependency management)
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
e-voting-system/
|
|
├── backend/ # FastAPI application
|
|
│ ├── main.py # Entry point
|
|
│ ├── routes/ # API endpoints (auth, elections, votes)
|
|
│ ├── models.py # Database models
|
|
│ ├── schemas.py # Pydantic schemas
|
|
│ ├── config.py # Configuration
|
|
│ └── crypto/ # Cryptography modules
|
|
├── frontend/ # Next.js application
|
|
│ ├── app/ # Application pages
|
|
│ ├── components/ # React components
|
|
│ ├── lib/ # Utilities (API client, auth context)
|
|
│ └── package.json # npm dependencies
|
|
└── pyproject.toml # Python dependencies
|
|
|
|
```
|
|
|
|
## Quick Start (Both Services)
|
|
|
|
### Prerequisites Setup
|
|
|
|
1. **Python Environment (Backend)**
|
|
|
|
```bash
|
|
# Install Poetry
|
|
curl -sSL https://install.python-poetry.org | python3 -
|
|
|
|
# Install Python dependencies
|
|
cd /home/sorti/projects/CIA/e-voting-system
|
|
poetry install
|
|
```
|
|
|
|
2. **Node.js Environment (Frontend)**
|
|
|
|
```bash
|
|
cd /home/sorti/projects/CIA/e-voting-system/frontend
|
|
npm install
|
|
```
|
|
|
|
### Database Setup
|
|
|
|
The backend uses MySQL by default. For development, you can use SQLite instead.
|
|
|
|
**Option 1: Using SQLite (Easy for Development)**
|
|
|
|
```bash
|
|
# Set environment variable to use SQLite
|
|
export DB_URL="sqlite:///./evoting.db"
|
|
```
|
|
|
|
**Option 2: Using MySQL (Production-like)**
|
|
|
|
```bash
|
|
# Start MySQL (if using Docker)
|
|
docker run --name mysql-evoting -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=evoting_db -p 3306:3306 -d mysql:8.0
|
|
|
|
# Or connect to existing MySQL instance
|
|
export DB_HOST=localhost
|
|
export DB_PORT=3306
|
|
export DB_NAME=evoting_db
|
|
export DB_USER=evoting_user
|
|
export DB_PASSWORD=evoting_pass123
|
|
```
|
|
|
|
### Running Both Services
|
|
|
|
**Terminal 1: Start Backend**
|
|
|
|
```bash
|
|
cd /home/sorti/projects/CIA/e-voting-system
|
|
|
|
# Activate Poetry shell or use poetry run
|
|
poetry shell
|
|
# or
|
|
poetry run uvicorn backend.main:app --reload --host 0.0.0.0 --port 8000
|
|
```
|
|
|
|
Backend will be available at: `http://localhost:8000`
|
|
- Swagger UI: `http://localhost:8000/docs`
|
|
- ReDoc: `http://localhost:8000/redoc`
|
|
|
|
**Terminal 2: Start Frontend**
|
|
|
|
```bash
|
|
cd /home/sorti/projects/CIA/e-voting-system/frontend
|
|
|
|
# Create .env.local if it doesn't exist
|
|
cat > .env.local << EOF
|
|
NEXT_PUBLIC_API_URL=http://localhost:8000
|
|
EOF
|
|
|
|
# Start development server
|
|
npm run dev
|
|
```
|
|
|
|
Frontend will be available at: `http://localhost:3000`
|
|
|
|
## API Endpoints
|
|
|
|
### Authentication
|
|
|
|
```http
|
|
POST /api/auth/register
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "securepass123",
|
|
"first_name": "Jean",
|
|
"last_name": "Dupont"
|
|
}
|
|
|
|
Response 200:
|
|
{
|
|
"access_token": "eyJhbGc...",
|
|
"expires_in": 1800,
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"first_name": "Jean",
|
|
"last_name": "Dupont"
|
|
}
|
|
```
|
|
|
|
```http
|
|
POST /api/auth/login
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "securepass123"
|
|
}
|
|
|
|
Response 200:
|
|
{
|
|
"access_token": "eyJhbGc...",
|
|
"expires_in": 1800,
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"first_name": "Jean",
|
|
"last_name": "Dupont"
|
|
}
|
|
```
|
|
|
|
```http
|
|
GET /api/auth/profile
|
|
Authorization: Bearer <token>
|
|
|
|
Response 200:
|
|
{
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"first_name": "Jean",
|
|
"last_name": "Dupont",
|
|
"created_at": "2025-11-06T12:00:00Z"
|
|
}
|
|
```
|
|
|
|
### Elections
|
|
|
|
```http
|
|
GET /api/elections/active
|
|
Response 200: [Election, ...]
|
|
|
|
GET /api/elections/upcoming
|
|
Response 200: [Election, ...]
|
|
|
|
GET /api/elections/completed
|
|
Response 200: [Election, ...]
|
|
|
|
GET /api/elections/{id}
|
|
Response 200: Election
|
|
|
|
GET /api/elections/{id}/candidates
|
|
Response 200: [Candidate, ...]
|
|
|
|
GET /api/elections/{id}/results
|
|
Response 200: ElectionResultResponse
|
|
```
|
|
|
|
### Votes
|
|
|
|
```http
|
|
POST /api/votes
|
|
Authorization: Bearer <token>
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"election_id": 1,
|
|
"choix": "Candidate Name"
|
|
}
|
|
|
|
Response 200:
|
|
{
|
|
"id": 1,
|
|
"ballot_hash": "abc123...",
|
|
"timestamp": "2025-11-06T12:00:00Z"
|
|
}
|
|
|
|
GET /api/votes/status?election_id=1
|
|
Authorization: Bearer <token>
|
|
|
|
Response 200:
|
|
{
|
|
"has_voted": false
|
|
}
|
|
|
|
GET /api/votes/history
|
|
Authorization: Bearer <token>
|
|
|
|
Response 200: [VoteHistory, ...]
|
|
```
|
|
|
|
## Frontend Features Integrated
|
|
|
|
### Pages
|
|
|
|
- ✅ **Home** (`/`) - Landing page with call-to-action
|
|
- ✅ **Login** (`/auth/login`) - Authentication with backend
|
|
- ✅ **Register** (`/auth/register`) - User registration
|
|
- ✅ **Dashboard** (`/dashboard`) - Loads active elections from API
|
|
- ✅ **Active Votes** (`/dashboard/votes/active`) - List active elections
|
|
- ✅ **Upcoming Votes** (`/dashboard/votes/upcoming`) - Timeline of future elections
|
|
- ✅ **Vote History** (`/dashboard/votes/history`) - Past votes
|
|
- ✅ **Archives** (`/dashboard/votes/archives`) - Historical elections
|
|
- ✅ **Profile** (`/dashboard/profile`) - User profile management
|
|
|
|
### Authentication Flow
|
|
|
|
1. User fills login/register form
|
|
2. Form data sent to backend (`/api/auth/login` or `/api/auth/register`)
|
|
3. Backend validates credentials and returns JWT token
|
|
4. Frontend stores token in localStorage
|
|
5. Token included in Authorization header for protected endpoints
|
|
6. Dashboard pages protected with `ProtectedRoute` component
|
|
7. Non-authenticated users redirected to login
|
|
|
|
### Protected Routes
|
|
|
|
- Dashboard and all sub-pages require authentication
|
|
- Automatic redirect to login if token is missing/expired
|
|
- User name displayed in dashboard header
|
|
- Logout clears token and redirects to home
|
|
|
|
## Testing the Integration
|
|
|
|
### Manual Testing
|
|
|
|
1. **Register a new user**
|
|
- Go to `http://localhost:3000/auth/register`
|
|
- Fill in email, name, and password
|
|
- Submit form
|
|
- Should redirect to dashboard
|
|
|
|
2. **Login**
|
|
- Go to `http://localhost:3000/auth/login`
|
|
- Use registered email and password
|
|
- Should redirect to dashboard
|
|
|
|
3. **View Elections**
|
|
- Dashboard loads active elections from backend
|
|
- See real election data with candidate counts
|
|
- Loading spinner shows while fetching data
|
|
|
|
4. **Logout**
|
|
- Click "Déconnexion" button in dashboard sidebar
|
|
- Should redirect to home page
|
|
- Token removed from localStorage
|
|
|
|
### API Testing with curl
|
|
|
|
```bash
|
|
# Register user
|
|
curl -X POST http://localhost:8000/api/auth/register \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"email":"test@example.com","password":"testpass123","first_name":"Test","last_name":"User"}'
|
|
|
|
# Login
|
|
curl -X POST http://localhost:8000/api/auth/login \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"email":"test@example.com","password":"testpass123"}'
|
|
|
|
# Get active elections (with token)
|
|
curl -X GET http://localhost:8000/api/elections/active \
|
|
-H "Authorization: Bearer YOUR_TOKEN"
|
|
|
|
# Get profile
|
|
curl -X GET http://localhost:8000/api/auth/profile \
|
|
-H "Authorization: Bearer YOUR_TOKEN"
|
|
```
|
|
|
|
### Testing with Frontend
|
|
|
|
1. **Check Network Tab (DevTools)**
|
|
- Open browser DevTools (F12)
|
|
- Go to Network tab
|
|
- Try logging in
|
|
- Should see POST request to `http://localhost:8000/api/auth/login`
|
|
- Response includes `access_token`
|
|
|
|
2. **Check Console Tab**
|
|
- No CORS errors should appear
|
|
- Auth context logs should show user data
|
|
|
|
3. **Check Storage Tab**
|
|
- `localStorage` should contain `auth_token` after login
|
|
- Token removed after logout
|
|
|
|
## Environment Variables
|
|
|
|
### Backend (.env or export)
|
|
|
|
```bash
|
|
# Database
|
|
DB_HOST=localhost
|
|
DB_PORT=3306
|
|
DB_NAME=evoting_db
|
|
DB_USER=evoting_user
|
|
DB_PASSWORD=evoting_pass123
|
|
|
|
# Security
|
|
SECRET_KEY=your-secret-key-change-in-production
|
|
DEBUG=false
|
|
|
|
# Application
|
|
APP_NAME="E-Voting System API"
|
|
```
|
|
|
|
### Frontend (.env.local)
|
|
|
|
```bash
|
|
NEXT_PUBLIC_API_URL=http://localhost:8000
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### "Connection refused" error on login
|
|
|
|
- Ensure backend is running on port 8000
|
|
- Check `NEXT_PUBLIC_API_URL` in frontend `.env.local`
|
|
- Verify backend is accessible: `curl http://localhost:8000/health`
|
|
|
|
### "CORS error" when logging in
|
|
|
|
- CORS is already enabled in backend (`allow_origins=["*"]`)
|
|
- Check browser console for specific CORS error
|
|
- Verify backend CORS middleware is configured
|
|
|
|
### Token not persisted after page refresh
|
|
|
|
- Check localStorage in DevTools (Storage tab)
|
|
- Verify `auth_token` key is being set
|
|
- Check browser privacy/incognito mode (may prevent localStorage)
|
|
|
|
### "Unauthorized" errors on protected endpoints
|
|
|
|
- Token may have expired (30 minutes by default)
|
|
- Re-login to get new token
|
|
- Check `Authorization` header is being sent in requests
|
|
|
|
### Frontend can't find API
|
|
|
|
- Ensure backend is running: `uvicorn backend.main:app --reload`
|
|
- Check port: should be 8000
|
|
- Check API URL in `.env.local`: `http://localhost:8000`
|
|
- Try health check: `curl http://localhost:8000/health`
|
|
|
|
## Performance Optimizations
|
|
|
|
### Frontend Optimizations
|
|
|
|
- Auto-split code by routes
|
|
- Tailwind CSS: ~17 kB gzipped
|
|
- Shared JS bundle: ~102 kB
|
|
- Individual pages: 2-4 kB each
|
|
|
|
### Backend Optimizations
|
|
|
|
- Use connection pooling
|
|
- Index database columns
|
|
- Cache election data
|
|
- Compress API responses
|
|
|
|
## Security Considerations
|
|
|
|
### Development vs Production
|
|
|
|
**Development (Current)**
|
|
- CORS: Allow all origins (`["*"]`)
|
|
- Debug mode: enabled
|
|
- Secret key: default (not secure)
|
|
- HTTPS: not required
|
|
|
|
**Production (Required)**
|
|
- CORS: Restrict to frontend domain
|
|
- Debug mode: disabled
|
|
- Secret key: strong, secure, environment variable
|
|
- HTTPS: required for all API calls
|
|
- Token expiration: reduce from 30 to 15 minutes
|
|
- Rate limiting: add to prevent abuse
|
|
- Hashing: use strong algorithm (bcrypt already configured)
|
|
|
|
### Authentication Security
|
|
|
|
- ✅ Passwords hashed with bcrypt
|
|
- ✅ JWT tokens with expiration
|
|
- ✅ Token stored in localStorage (vulnerable to XSS)
|
|
- ⚠️ Consider HttpOnly cookies for production
|
|
- ✅ HTTPS required in production
|
|
|
|
## Next Steps
|
|
|
|
1. **Database Population**: Create test elections and candidates
|
|
2. **Voting Interface**: Implement actual vote submission
|
|
3. **Results Display**: Show election results with charts
|
|
4. **Form Validation**: Add Zod validation to frontend forms
|
|
5. **Error Handling**: Implement error boundaries
|
|
6. **Testing**: Add unit and E2E tests
|
|
7. **Deployment**: Deploy to production environment
|
|
|
|
## Support
|
|
|
|
- Backend Docs: `http://localhost:8000/docs` (Swagger)
|
|
- Frontend Docs: `frontend/FRONTEND_NEXTJS_GUIDE.md`
|
|
- Integration Guide: `NEXT_STEPS.md`
|
|
|
|
---
|
|
|
|
**Status**: Backend and frontend integrated and ready for testing
|
|
**Date**: 2025-11-06
|
|
**Branch**: UI
|