Compare commits
No commits in common. "41e7fc08ed2d4fd9cdd66a30e8648d65980d786c" and "3efdabdbbd8fe00f857298f9f208928f626ccb68" have entirely different histories.
41e7fc08ed
...
3efdabdbbd
@ -1,238 +0,0 @@
|
|||||||
# Frontend Development Mode - Setup & Usage
|
|
||||||
|
|
||||||
## 🚀 Quick Start
|
|
||||||
|
|
||||||
### Option 1: Using the Helper Script (Recommended)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Start frontend in development mode
|
|
||||||
./dev-mode.sh start
|
|
||||||
|
|
||||||
# In another terminal, stream logs
|
|
||||||
./dev-mode.sh logs
|
|
||||||
|
|
||||||
# To stop
|
|
||||||
./dev-mode.sh stop
|
|
||||||
```
|
|
||||||
|
|
||||||
### Option 2: Direct Docker Compose Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Start dev frontend with other services
|
|
||||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml up frontend-dev
|
|
||||||
|
|
||||||
# Stream logs
|
|
||||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f frontend-dev
|
|
||||||
|
|
||||||
# Stop
|
|
||||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml down
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✨ Features in Development Mode
|
|
||||||
|
|
||||||
### ✓ Hot Module Reload (HMR)
|
|
||||||
- Changes to `.ts`, `.tsx`, `.css` files automatically refresh in browser
|
|
||||||
- No need to rebuild container
|
|
||||||
- Source maps for debugging
|
|
||||||
|
|
||||||
### ✓ Detailed Logging
|
|
||||||
- Browser console logs visible in Docker logs
|
|
||||||
- Server-side render logs
|
|
||||||
- API request/response debugging
|
|
||||||
- Network timing information
|
|
||||||
|
|
||||||
### ✓ Development Tools
|
|
||||||
- Next.js dev server with full diagnostics
|
|
||||||
- TypeScript error messages with line numbers
|
|
||||||
- React Fast Refresh for component updates
|
|
||||||
- Network tab in browser DevTools
|
|
||||||
|
|
||||||
### ✓ Volume Mounting
|
|
||||||
- `./frontend:/app` - all source code hot-reloaded
|
|
||||||
- `/app/node_modules` - isolated for performance
|
|
||||||
- `/app/.next` - isolated build cache
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 Available Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Start development mode
|
|
||||||
./dev-mode.sh start
|
|
||||||
|
|
||||||
# Stop development mode
|
|
||||||
./dev-mode.sh stop
|
|
||||||
|
|
||||||
# Stream frontend logs only
|
|
||||||
./dev-mode.sh logs
|
|
||||||
|
|
||||||
# Stream ALL services logs
|
|
||||||
./dev-mode.sh logs-all
|
|
||||||
|
|
||||||
# Rebuild dev image (after package.json changes)
|
|
||||||
./dev-mode.sh rebuild
|
|
||||||
|
|
||||||
# Open shell in dev container
|
|
||||||
./dev-mode.sh shell
|
|
||||||
|
|
||||||
# Check container status
|
|
||||||
./dev-mode.sh status
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📍 Access Points
|
|
||||||
|
|
||||||
| Service | URL | Purpose |
|
|
||||||
|---------|-----|---------|
|
|
||||||
| Frontend (Dev) | http://localhost:3000 | Application with hot reload |
|
|
||||||
| Backend API | http://localhost:8000 | API endpoint |
|
|
||||||
| API Docs | http://localhost:8000/docs | Swagger documentation |
|
|
||||||
| Database Admin | http://localhost:8081 | MariaDB management |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔍 Debugging Tips
|
|
||||||
|
|
||||||
### View Detailed Frontend Logs
|
|
||||||
```bash
|
|
||||||
./dev-mode.sh logs
|
|
||||||
|
|
||||||
# Or use grep to filter
|
|
||||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f frontend-dev | grep -i error
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check All Services
|
|
||||||
```bash
|
|
||||||
./dev-mode.sh logs-all
|
|
||||||
```
|
|
||||||
|
|
||||||
### Open Terminal in Container
|
|
||||||
```bash
|
|
||||||
./dev-mode.sh shell
|
|
||||||
|
|
||||||
# Inside container, you can run:
|
|
||||||
npm run lint
|
|
||||||
npm run type-check
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Browser DevTools
|
|
||||||
1. Open http://localhost:3000
|
|
||||||
2. Open DevTools (F12 or Ctrl+Shift+I)
|
|
||||||
3. View:
|
|
||||||
- **Console** - see all logs from Next.js
|
|
||||||
- **Network** - see API requests/responses
|
|
||||||
- **Sources** - debug TypeScript code
|
|
||||||
- **Application** - inspect state/localStorage
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛠️ When to Rebuild
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# After changing package.json or package-lock.json
|
|
||||||
./dev-mode.sh rebuild
|
|
||||||
|
|
||||||
# After changing environment variables in Dockerfile.frontend.dev
|
|
||||||
./dev-mode.sh rebuild
|
|
||||||
|
|
||||||
# Usually NOT needed for code changes (hot reload works)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Environment Variables in Dev Mode
|
|
||||||
|
|
||||||
Automatically set in `docker-compose.dev.yml`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
NODE_ENV: development # Enable dev features
|
|
||||||
NEXT_PUBLIC_DEBUG: 'true' # Frontend debug mode
|
|
||||||
NEXT_PUBLIC_API_URL: http://localhost:8000
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 Hot Reload Workflow
|
|
||||||
|
|
||||||
1. **Edit a file** → `frontend/components/something.tsx`
|
|
||||||
2. **Save** → File is mounted in container
|
|
||||||
3. **Next.js detects change** → ~500ms
|
|
||||||
4. **Fast Refresh** → Browser auto-reloads
|
|
||||||
5. **View in DevTools** → Console shows updates
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐛 Common Issues
|
|
||||||
|
|
||||||
### Container won't start
|
|
||||||
```bash
|
|
||||||
# Check logs
|
|
||||||
./dev-mode.sh logs
|
|
||||||
|
|
||||||
# Rebuild from scratch
|
|
||||||
./dev-mode.sh rebuild
|
|
||||||
./dev-mode.sh start
|
|
||||||
```
|
|
||||||
|
|
||||||
### Port 3000 already in use
|
|
||||||
```bash
|
|
||||||
# Change port in docker-compose.dev.yml
|
|
||||||
# Or kill existing process
|
|
||||||
lsof -ti:3000 | xargs kill -9
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changes not reflecting
|
|
||||||
```bash
|
|
||||||
# Try full refresh in browser
|
|
||||||
Ctrl+Shift+R (hard refresh)
|
|
||||||
|
|
||||||
# Or restart container
|
|
||||||
./dev-mode.sh stop
|
|
||||||
./dev-mode.sh start
|
|
||||||
```
|
|
||||||
|
|
||||||
### Need to see all npm commands
|
|
||||||
```bash
|
|
||||||
./dev-mode.sh shell
|
|
||||||
cat package.json | grep -A 10 '"scripts"'
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 Production vs Development
|
|
||||||
|
|
||||||
| Aspect | Production | Development |
|
|
||||||
|--------|-----------|-------------|
|
|
||||||
| Build | Optimized, minified | Unoptimized for speed |
|
|
||||||
| HMR | ✗ No | ✓ Yes |
|
|
||||||
| Logging | Minimal | Verbose |
|
|
||||||
| Performance | Fast | Slower (for debugging) |
|
|
||||||
| File Size | ~100KB | ~5MB |
|
|
||||||
| Startup | 5-10s | 30-60s |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Performance Notes
|
|
||||||
|
|
||||||
- Dev mode is intentionally verbose for debugging
|
|
||||||
- Larger bundle size than production
|
|
||||||
- Slower startup is normal
|
|
||||||
- HMR eliminates need for full rebuilds
|
|
||||||
|
|
||||||
Use production mode for performance testing.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 Further Reading
|
|
||||||
|
|
||||||
- [Next.js Dev Server](https://nextjs.org/docs/app/api-reference/cli/next/dev)
|
|
||||||
- [Docker Compose Override](https://docs.docker.com/compose/extends/)
|
|
||||||
- [React DevTools](https://react-devtools-tutorial.vercel.app/)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Last Updated:** 2025-11-07
|
|
||||||
@ -1,99 +0,0 @@
|
|||||||
# Quick Development Mode Setup
|
|
||||||
|
|
||||||
## ⚡ 30-Second Start
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Make sure you're in the project root
|
|
||||||
cd /home/sorti/projects/CIA/e-voting-system
|
|
||||||
|
|
||||||
# Start development mode
|
|
||||||
./dev-mode.sh start
|
|
||||||
```
|
|
||||||
|
|
||||||
That's it! Your frontend will be running with:
|
|
||||||
- ✓ Hot reload on every file change
|
|
||||||
- ✓ Full console logs in Docker
|
|
||||||
- ✓ TypeScript type checking
|
|
||||||
- ✓ Source maps for debugging
|
|
||||||
|
|
||||||
## 📺 View Logs in Real-Time
|
|
||||||
|
|
||||||
Open a **new terminal** and run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./dev-mode.sh logs
|
|
||||||
```
|
|
||||||
|
|
||||||
Now you'll see every log from:
|
|
||||||
- Next.js startup messages
|
|
||||||
- Component renders
|
|
||||||
- API calls
|
|
||||||
- Console.log() statements
|
|
||||||
- Errors with full stack traces
|
|
||||||
|
|
||||||
## 🌐 Access Your App
|
|
||||||
|
|
||||||
Open in browser: **http://localhost:3000**
|
|
||||||
|
|
||||||
Press `F12` to open DevTools and see:
|
|
||||||
- Console logs from both server and client
|
|
||||||
- Network requests to `/api/`
|
|
||||||
- Component hierarchy in React DevTools
|
|
||||||
|
|
||||||
## 🛑 Stop Development Mode
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./dev-mode.sh stop
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📝 Edit Files
|
|
||||||
|
|
||||||
1. Edit any file in `frontend/` directory
|
|
||||||
2. Save
|
|
||||||
3. Next.js detects change (~500ms)
|
|
||||||
4. Browser auto-refreshes
|
|
||||||
5. See console logs in terminal
|
|
||||||
|
|
||||||
**No container rebuild needed!** 🎉
|
|
||||||
|
|
||||||
## 🆘 Troubleshooting
|
|
||||||
|
|
||||||
**Can't see logs?**
|
|
||||||
```bash
|
|
||||||
./dev-mode.sh logs
|
|
||||||
```
|
|
||||||
|
|
||||||
**Port 3000 in use?**
|
|
||||||
```bash
|
|
||||||
lsof -ti:3000 | xargs kill -9
|
|
||||||
./dev-mode.sh start
|
|
||||||
```
|
|
||||||
|
|
||||||
**Need a shell in container?**
|
|
||||||
```bash
|
|
||||||
./dev-mode.sh shell
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Common Dev Tasks
|
|
||||||
|
|
||||||
| Task | Command |
|
|
||||||
|------|---------|
|
|
||||||
| Start dev | `./dev-mode.sh start` |
|
|
||||||
| View logs | `./dev-mode.sh logs` |
|
|
||||||
| Stop dev | `./dev-mode.sh stop` |
|
|
||||||
| Rebuild after npm install | `./dev-mode.sh rebuild` |
|
|
||||||
| Open shell | `./dev-mode.sh shell` |
|
|
||||||
| Check status | `./dev-mode.sh status` |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Next Steps
|
|
||||||
|
|
||||||
1. ✓ Start dev mode: `./dev-mode.sh start`
|
|
||||||
2. ✓ View logs: `./dev-mode.sh logs` (in another terminal)
|
|
||||||
3. ✓ Open browser: http://localhost:3000
|
|
||||||
4. ✓ Edit some code and see instant updates!
|
|
||||||
|
|
||||||
For more info, see [DEV_MODE.md](./DEV_MODE.md)
|
|
||||||
@ -499,18 +499,15 @@ async def setup_election(
|
|||||||
|
|
||||||
# Générer les clés ElGamal si nécessaire
|
# Générer les clés ElGamal si nécessaire
|
||||||
if not election.public_key:
|
if not election.public_key:
|
||||||
elgamal = ElGamal()
|
elgamal = ElGamalEncryption(p=election.elgamal_p or 23, g=election.elgamal_g or 5)
|
||||||
# Store as base64-encoded bytes (database column is LargeBinary)
|
election.public_key = elgamal.public_key_bytes
|
||||||
# public_key_bytes returns UTF-8 "p:g:h", then encode to base64
|
|
||||||
election.public_key = base64.b64encode(elgamal.public_key_bytes)
|
|
||||||
db.add(election)
|
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": "initialized",
|
"status": "initialized",
|
||||||
"election_id": election_id,
|
"election_id": election_id,
|
||||||
"public_keys": {
|
"public_keys": {
|
||||||
"elgamal_pubkey": election.public_key.decode('utf-8') if election.public_key else None
|
"elgamal_pubkey": base64.b64encode(election.public_key).decode() if election.public_key else None
|
||||||
},
|
},
|
||||||
"blockchain_blocks": blockchain.get_block_count()
|
"blockchain_blocks": blockchain.get_block_count()
|
||||||
}
|
}
|
||||||
@ -547,7 +544,7 @@ async def get_public_keys(
|
|||||||
)
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"elgamal_pubkey": election.public_key.decode('utf-8') if election.public_key else None
|
"elgamal_pubkey": base64.b64encode(election.public_key).decode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,83 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# E-Voting System - Frontend Development Mode Helper
|
|
||||||
# This script helps run the Next.js frontend in development mode with detailed logging
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
case "${1:-help}" in
|
|
||||||
start)
|
|
||||||
echo "🚀 Starting frontend in DEVELOPMENT mode with full logging..."
|
|
||||||
echo ""
|
|
||||||
echo "Features:"
|
|
||||||
echo " ✓ Hot reload on file changes"
|
|
||||||
echo " ✓ Detailed browser console logs"
|
|
||||||
echo " ✓ Server-side render logs"
|
|
||||||
echo " ✓ API request/response logs"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Stop the production frontend if running
|
|
||||||
if docker compose ps | grep -q "evoting_frontend"; then
|
|
||||||
echo "Stopping production frontend..."
|
|
||||||
docker compose stop frontend
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Start dev frontend with other services
|
|
||||||
echo "Starting all services..."
|
|
||||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml up frontend-dev
|
|
||||||
;;
|
|
||||||
|
|
||||||
stop)
|
|
||||||
echo "⏹️ Stopping frontend development mode..."
|
|
||||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml down
|
|
||||||
;;
|
|
||||||
|
|
||||||
logs)
|
|
||||||
echo "📋 Showing frontend development logs (streaming)..."
|
|
||||||
echo ""
|
|
||||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f frontend-dev
|
|
||||||
;;
|
|
||||||
|
|
||||||
logs-all)
|
|
||||||
echo "📋 Showing all services logs..."
|
|
||||||
echo ""
|
|
||||||
docker compose logs -f
|
|
||||||
;;
|
|
||||||
|
|
||||||
rebuild)
|
|
||||||
echo "🔨 Rebuilding frontend dev image..."
|
|
||||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml build --no-cache frontend-dev
|
|
||||||
;;
|
|
||||||
|
|
||||||
shell)
|
|
||||||
echo "🐚 Opening shell in frontend dev container..."
|
|
||||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml exec frontend-dev sh
|
|
||||||
;;
|
|
||||||
|
|
||||||
status)
|
|
||||||
echo "📊 Frontend development status:"
|
|
||||||
echo ""
|
|
||||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml ps frontend-dev
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
echo "E-Voting System - Frontend Development Mode Helper"
|
|
||||||
echo ""
|
|
||||||
echo "Usage: ./dev-mode.sh [command]"
|
|
||||||
echo ""
|
|
||||||
echo "Commands:"
|
|
||||||
echo " start - Start frontend in development mode with hot reload"
|
|
||||||
echo " stop - Stop development mode"
|
|
||||||
echo " logs - Show frontend logs (streaming)"
|
|
||||||
echo " logs-all - Show all services logs"
|
|
||||||
echo " rebuild - Rebuild frontend dev image"
|
|
||||||
echo " shell - Open shell in dev container"
|
|
||||||
echo " status - Show development container status"
|
|
||||||
echo ""
|
|
||||||
echo "Examples:"
|
|
||||||
echo " ./dev-mode.sh start # Start dev mode"
|
|
||||||
echo " ./dev-mode.sh logs # Stream logs"
|
|
||||||
echo " ./dev-mode.sh logs-all # All services"
|
|
||||||
echo ""
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
@ -1,43 +1,72 @@
|
|||||||
version: '3.8'
|
version: '3.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# Development version of the frontend with hot reload and verbose logging
|
mariadb:
|
||||||
frontend-dev:
|
image: mariadb:latest
|
||||||
|
container_name: evoting_db
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-rootpass123}
|
||||||
|
MYSQL_DATABASE: ${DB_NAME:-evoting_db}
|
||||||
|
MYSQL_USER: ${DB_USER:-evoting_user}
|
||||||
|
MYSQL_PASSWORD: ${DB_PASSWORD:-evoting_pass123}
|
||||||
|
ports:
|
||||||
|
- "${DB_PORT:-3306}:3306"
|
||||||
|
volumes:
|
||||||
|
- evoting_data:/var/lib/mysql
|
||||||
|
- ./docker/init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||||
|
networks:
|
||||||
|
- evoting_network
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mariadb-admin", "ping", "-h", "localhost", "--silent"]
|
||||||
|
timeout: 20s
|
||||||
|
retries: 10
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: docker/Dockerfile.backend
|
||||||
|
container_name: evoting_backend
|
||||||
|
environment:
|
||||||
|
DB_HOST: mariadb
|
||||||
|
DB_PORT: 3306
|
||||||
|
DB_NAME: ${DB_NAME:-evoting_db}
|
||||||
|
DB_USER: ${DB_USER:-evoting_user}
|
||||||
|
DB_PASSWORD: ${DB_PASSWORD:-evoting_pass123}
|
||||||
|
SECRET_KEY: ${SECRET_KEY:-your-secret-key-change-in-production}
|
||||||
|
DEBUG: ${DEBUG:-false}
|
||||||
|
ports:
|
||||||
|
- "${BACKEND_PORT:-8000}:8000"
|
||||||
|
depends_on:
|
||||||
|
mariadb:
|
||||||
|
condition: service_healthy
|
||||||
|
volumes:
|
||||||
|
- ./backend:/app/backend
|
||||||
|
networks:
|
||||||
|
- evoting_network
|
||||||
|
command: uvicorn backend.main:app --host 0.0.0.0 --port 8000 --reload
|
||||||
|
|
||||||
|
frontend:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: docker/Dockerfile.frontend.dev
|
dockerfile: docker/Dockerfile.frontend.dev
|
||||||
container_name: evoting_frontend_dev
|
args:
|
||||||
restart: unless-stopped
|
REACT_APP_API_URL: http://backend:8000
|
||||||
|
container_name: evoting_frontend
|
||||||
ports:
|
ports:
|
||||||
- "${FRONTEND_PORT:-3000}:3000"
|
- "${FRONTEND_PORT:-3000}:3000"
|
||||||
depends_on:
|
depends_on:
|
||||||
backend:
|
- backend
|
||||||
condition: service_healthy
|
|
||||||
validator-1:
|
|
||||||
condition: service_healthy
|
|
||||||
validator-2:
|
|
||||||
condition: service_healthy
|
|
||||||
validator-3:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
NEXT_PUBLIC_API_URL: http://localhost:${BACKEND_PORT:-8000}
|
|
||||||
NODE_ENV: development
|
|
||||||
NEXT_PUBLIC_DEBUG: 'true'
|
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
||||||
volumes:
|
volumes:
|
||||||
# Mount source code for hot reload
|
- ./frontend/src:/app/src
|
||||||
- ./frontend:/app
|
- ./frontend/public:/app/public
|
||||||
- /app/node_modules
|
|
||||||
- /app/.next
|
|
||||||
networks:
|
networks:
|
||||||
- evoting_network
|
- evoting_network
|
||||||
logging:
|
stdin_open: true
|
||||||
driver: "json-file"
|
tty: true
|
||||||
options:
|
|
||||||
max-size: "50m"
|
volumes:
|
||||||
max-file: "5"
|
evoting_data:
|
||||||
# Run in development mode with verbose output
|
|
||||||
command: npm run dev -- -H 0.0.0.0 --port 3000
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
evoting_network:
|
evoting_network:
|
||||||
|
|||||||
@ -15,13 +15,7 @@ COPY frontend/ .
|
|||||||
ARG REACT_APP_API_URL=http://backend:8000
|
ARG REACT_APP_API_URL=http://backend:8000
|
||||||
ENV REACT_APP_API_URL=${REACT_APP_API_URL}
|
ENV REACT_APP_API_URL=${REACT_APP_API_URL}
|
||||||
|
|
||||||
# Development environment variables for detailed logging
|
|
||||||
ENV NODE_ENV=development
|
|
||||||
ENV NEXT_PUBLIC_DEBUG=true
|
|
||||||
ENV DEBUG=*
|
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
# Mode développement avec hot reload et logs verbeux
|
# Mode développement avec hot reload (npm start)
|
||||||
# --turbopack-trace=verbose pour plus de détails
|
CMD ["npm", "start"]
|
||||||
CMD ["npm", "run", "dev", "--", "-H", "0.0.0.0", "--port", "3000"]
|
|
||||||
|
|||||||
@ -95,16 +95,7 @@ export default function BlockchainPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
// Ensure blocks array exists
|
setBlockchainData(data)
|
||||||
const blockchainData = {
|
|
||||||
blocks: data.blocks || [],
|
|
||||||
verification: data.verification || {
|
|
||||||
chain_valid: true,
|
|
||||||
total_blocks: 0,
|
|
||||||
total_votes: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setBlockchainData(blockchainData)
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const errorMessage = err instanceof Error ? err.message : "Erreur inconnue"
|
const errorMessage = err instanceof Error ? err.message : "Erreur inconnue"
|
||||||
setError(errorMessage)
|
setError(errorMessage)
|
||||||
@ -276,7 +267,7 @@ export default function BlockchainPage() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Empty State */}
|
{/* Empty State */}
|
||||||
{blockchainData && blockchainData.blocks && blockchainData.blocks.length === 0 && (
|
{blockchainData && blockchainData.blocks.length === 0 && (
|
||||||
<Card>
|
<Card>
|
||||||
<CardContent className="pt-6 text-center py-12">
|
<CardContent className="pt-6 text-center py-12">
|
||||||
<div className="text-5xl mb-4">⛓️</div>
|
<div className="text-5xl mb-4">⛓️</div>
|
||||||
|
|||||||
@ -39,12 +39,7 @@ export default function ActiveVotesPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
// Ensure elections is an array and each has candidates
|
setElections(data || [])
|
||||||
const elections = Array.isArray(data) ? data.map(e => ({
|
|
||||||
...e,
|
|
||||||
candidates: e.candidates || []
|
|
||||||
})) : []
|
|
||||||
setElections(elections)
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const message = err instanceof Error ? err.message : "Erreur lors du chargement"
|
const message = err instanceof Error ? err.message : "Erreur lors du chargement"
|
||||||
setError(message)
|
setError(message)
|
||||||
|
|||||||
@ -70,57 +70,69 @@ export class ElGamalEncryption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Decode base64: base64("p:g:h") → "p:g:h"
|
// Validate input
|
||||||
const publicKeyStr = this._decodeBase64(publicKeyBase64);
|
if (!publicKeyBase64 || typeof publicKeyBase64 !== "string") {
|
||||||
const [p, g, h] = this._parsePublicKey(publicKeyStr);
|
throw new Error("Invalid public key: must be a non-empty string");
|
||||||
|
}
|
||||||
|
|
||||||
// Generate random r for encryption
|
// Decode the base64 public key
|
||||||
const r = BigInt(Math.floor(Math.random() * (Number(p) - 2)) + 1);
|
// Format from backend: base64("p:g:h") where p, g, h are decimal numbers
|
||||||
|
let publicKeyStr: string;
|
||||||
|
try {
|
||||||
|
publicKeyStr = atob(publicKeyBase64);
|
||||||
|
} catch (e) {
|
||||||
|
const errorMsg = e instanceof Error ? e.message : String(e);
|
||||||
|
throw new Error(`Failed to decode public key from base64: ${errorMsg}`);
|
||||||
|
}
|
||||||
|
|
||||||
// ElGamal: (c1, c2) = (g^r mod p, m * h^r mod p)
|
// Validate decoded string
|
||||||
|
if (!publicKeyStr || typeof publicKeyStr !== "string") {
|
||||||
|
throw new Error("Invalid decoded public key: must be a non-empty string");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse public key (format: p:g:h separated by colons)
|
||||||
|
const publicKeyData = publicKeyStr.split(":");
|
||||||
|
|
||||||
|
if (publicKeyData.length < 3) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid public key format. Expected "p:g:h" but got "${publicKeyStr}"`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse and validate each component
|
||||||
|
let p: bigint, g: bigint, h: bigint;
|
||||||
|
try {
|
||||||
|
p = BigInt(publicKeyData[0]); // Prime
|
||||||
|
g = BigInt(publicKeyData[1]); // Generator
|
||||||
|
h = BigInt(publicKeyData[2]); // Public key = g^x mod p
|
||||||
|
} catch (e) {
|
||||||
|
const errorMsg = e instanceof Error ? e.message : String(e);
|
||||||
|
throw new Error(`Failed to parse public key numbers: ${errorMsg}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate parameters
|
||||||
|
if (p <= 0n || g <= 0n || h <= 0n) {
|
||||||
|
throw new Error("Invalid public key parameters: p, g, h must be positive");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate random number for encryption
|
||||||
|
const maxRandom = Number(p) - 2;
|
||||||
|
if (maxRandom <= 0) {
|
||||||
|
throw new Error("Public key prime p is too small");
|
||||||
|
}
|
||||||
|
const r = BigInt(Math.floor(Math.random() * maxRandom) + 1);
|
||||||
|
|
||||||
|
// ElGamal encryption: (c1, c2) = (g^r mod p, m * h^r mod p)
|
||||||
const c1 = this._modPow(g, r, p);
|
const c1 = this._modPow(g, r, p);
|
||||||
const c2 = (BigInt(vote) * this._modPow(h, r, p)) % p;
|
const c2 = (BigInt(vote) * this._modPow(h, r, p)) % p;
|
||||||
|
|
||||||
// Return encrypted as base64("c1:c2")
|
// Return as "c1:c2" in base64
|
||||||
return btoa(`${c1}:${c2}`);
|
const encrypted = `${c1.toString()}:${c2.toString()}`;
|
||||||
|
return btoa(encrypted);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const msg = error instanceof Error ? error.message : String(error);
|
const errorMsg = error instanceof Error ? error.message : String(error || "Unknown error");
|
||||||
throw new Error(`ElGamal encryption failed: ${msg}`);
|
console.error("ElGamal encryption failed:", errorMsg);
|
||||||
}
|
throw new Error(`Encryption failed: ${errorMsg}`);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode base64 string with clear error handling
|
|
||||||
*/
|
|
||||||
private static _decodeBase64(base64: string): string {
|
|
||||||
try {
|
|
||||||
return atob(base64);
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(`Invalid base64: ${base64.substring(0, 20)}... - ${e}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse public key from "p:g:h" format
|
|
||||||
*/
|
|
||||||
private static _parsePublicKey(keyStr: string): [bigint, bigint, bigint] {
|
|
||||||
const parts = keyStr.split(":");
|
|
||||||
if (parts.length !== 3) {
|
|
||||||
throw new Error(`Expected "p:g:h" format, got: ${keyStr}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const p = BigInt(parts[0]);
|
|
||||||
const g = BigInt(parts[1]);
|
|
||||||
const h = BigInt(parts[2]);
|
|
||||||
|
|
||||||
if (p <= 0n || g <= 0n || h <= 0n) {
|
|
||||||
throw new Error("p, g, h must all be positive");
|
|
||||||
}
|
|
||||||
|
|
||||||
return [p, g, h];
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(`Failed to parse key: ${e}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user