- Implement lazy MongoDB client initialization in backend/db/mongo_client.py. - Create Gunicorn configuration to ensure MongoDB client is initialized per worker. - Refactor database access layer to support MongoDB with a new MongoLockedTable adapter. - Add migration script to transfer existing TinyDB data to MongoDB, preserving idempotency. - Update tracking event handling to ensure deterministic ordering with a monotonic sequence. - Modify tests to use mongomock for MongoDB integration and ensure existing tests pass. - Add integration test script to run tests against a local MongoDB Docker container. - Document environment variables and migration process in specs/feat-database-migration.md.
204 lines
6.6 KiB
Markdown
204 lines
6.6 KiB
Markdown
# Reward - Chore & Reward Management System
|
|
|
|
A family-friendly application for managing chores, tasks, and rewards for children.
|
|
|
|
## 🏗️ Architecture
|
|
|
|
- **Backend**: Flask (Python) with TinyDB or MongoDB for data persistence
|
|
- **Frontend**: Vue 3 (TypeScript) with real-time SSE updates
|
|
- **Deployment**: Docker with nginx reverse proxy
|
|
|
|
## 🚀 Getting Started
|
|
|
|
### Backend
|
|
|
|
```bash
|
|
cd backend
|
|
python -m venv .venv
|
|
.venv\Scripts\activate # Windows
|
|
source .venv/bin/activate # Linux/Mac
|
|
pip install -r requirements.txt
|
|
python -m flask run --host=0.0.0.0 --port=5000
|
|
```
|
|
|
|
### Frontend
|
|
|
|
```bash
|
|
cd frontend
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
## 🔧 Configuration
|
|
|
|
### Environment Variables
|
|
|
|
| Variable | Description | Default |
|
|
| ---------------------------------- | --------------------------------------------- | ------------- |
|
|
| `ACCOUNT_DELETION_THRESHOLD_HOURS` | Hours to wait before deleting marked accounts | 720 (30 days) |
|
|
| `DB_ENV` | Database environment (`prod` or `test`) | `prod` |
|
|
| `DATA_ENV` | Data directory environment (`prod` or `test`) | `prod` |
|
|
| `USE_MONGODB` | Use MongoDB instead of TinyDB (`true`/`false`) | `false` |
|
|
| `MONGO_URI` | MongoDB connection URI (required when `USE_MONGODB=true`) | — |
|
|
| `MONGO_DB_NAME` | MongoDB database name (optional) | Parsed from `MONGO_URI`, or `chore_db`/`chore_db_test`/`chore_db_e2e` based on `DB_ENV` |
|
|
|
|
### Database Backend
|
|
|
|
The application supports two persistence backends:
|
|
|
|
- **TinyDB** (default): JSON-file storage in `backend/data/db/` (or `backend/test_data/db/` for `test`/`e2e`). No extra configuration needed.
|
|
- **MongoDB**: Set `USE_MONGODB=true` and provide `MONGO_URI`. Useful for production deployments and managed database hosting (e.g., MongoDB Atlas).
|
|
|
|
#### Migrating from TinyDB to MongoDB
|
|
|
|
```bash
|
|
cd backend
|
|
# Dry run to preview what will be migrated
|
|
python -m scripts.migrate_to_mongodb --dry-run
|
|
|
|
# Run the migration (backs up TinyDB files first)
|
|
python -m scripts.migrate_to_mongodb
|
|
```
|
|
|
|
The migration script reads the existing TinyDB JSON files and inserts each record into the matching MongoDB collection, skipping records that already exist. Original TinyDB files are backed up to `backend/data/db/backups/<timestamp>/`.
|
|
|
|
#### Rolling Back
|
|
|
|
To revert to TinyDB, simply set `USE_MONGODB=false` (or unset it). The original JSON files remain in place.
|
|
|
|
#### Gunicorn / Docker
|
|
|
|
When running multiple Gunicorn workers, each worker must create its own MongoDB client after forking. This is handled automatically by `backend/gunicorn.conf.py`, which is loaded by `backend/Dockerfile` via `-c gunicorn.conf.py`.
|
|
|
|
### Account Deletion Scheduler
|
|
|
|
The application includes an automated account deletion scheduler that removes user accounts marked for deletion after a configurable threshold period.
|
|
|
|
**Key Features:**
|
|
|
|
- Runs every hour checking for accounts due for deletion
|
|
- Configurable threshold between 24 hours (minimum) and 720 hours (maximum)
|
|
- Automatic retry on failure (max 3 attempts)
|
|
- Restart-safe: recovers from interruptions during deletion
|
|
|
|
**Deletion Process:**
|
|
When an account is marked for deletion, the scheduler will automatically:
|
|
|
|
1. Remove all pending rewards for the user's children
|
|
2. Remove all children belonging to the user
|
|
3. Remove all user-created tasks
|
|
4. Remove all user-created rewards
|
|
5. Remove uploaded images from database
|
|
6. Delete user's image directory from filesystem
|
|
7. Remove the user account
|
|
|
|
**Configuration:**
|
|
Set the deletion threshold via environment variable:
|
|
|
|
```bash
|
|
export ACCOUNT_DELETION_THRESHOLD_HOURS=168 # 7 days
|
|
```
|
|
|
|
**Monitoring:**
|
|
|
|
- Logs are written to `logs/account_deletion.log` with rotation (10MB max, 5 backups)
|
|
- Check logs for deletion summaries and any errors
|
|
|
|
## 🔌 API Endpoints
|
|
|
|
### Admin Endpoints
|
|
|
|
All admin endpoints require JWT authentication and **admin role**.
|
|
|
|
**Note:** Admin users must be created manually or via the provided script (`backend/scripts/create_admin.py`). The admin role cannot be assigned through the signup API for security reasons.
|
|
|
|
**Creating an Admin User:**
|
|
|
|
```bash
|
|
cd backend
|
|
python scripts/create_admin.py
|
|
```
|
|
|
|
#### Account Deletion Management
|
|
|
|
- `GET /api/admin/deletion-queue` - View users pending deletion
|
|
- `GET /api/admin/deletion-threshold` - Get current deletion threshold
|
|
- `PUT /api/admin/deletion-threshold` - Update deletion threshold (24-720 hours)
|
|
- `POST /api/admin/deletion-queue/trigger` - Manually trigger deletion scheduler
|
|
|
|
### User Endpoints
|
|
|
|
- `POST /api/user/mark-for-deletion` - Mark current user's account for deletion
|
|
- `GET /api/me` - Get current user info
|
|
- `POST /api/login` - User login
|
|
- `POST /api/logout` - User logout
|
|
|
|
## 🧪 Testing
|
|
|
|
### Backend Tests
|
|
|
|
```bash
|
|
cd backend
|
|
pytest tests/
|
|
```
|
|
|
|
### Frontend Tests
|
|
|
|
```bash
|
|
cd frontend
|
|
npm run test
|
|
```
|
|
|
|
## 📝 Features
|
|
|
|
- ✅ User authentication with JWT tokens
|
|
- ✅ Child profile management
|
|
- ✅ Task assignment and tracking
|
|
- ✅ Reward system
|
|
- ✅ Real-time updates via SSE
|
|
- ✅ Image upload and management
|
|
- ✅ Account deletion with grace period
|
|
- ✅ Automated cleanup scheduler
|
|
|
|
## 🔒 Security
|
|
|
|
- JWT tokens stored in HttpOnly, Secure, SameSite=Strict cookies
|
|
- **Role-Based Access Control (RBAC)**: Admin endpoints protected by admin role validation
|
|
- Admin users can only be created via direct database manipulation or provided script
|
|
- Regular users cannot escalate privileges to admin
|
|
- Account deletion requires email confirmation
|
|
- Marked accounts blocked from login immediately
|
|
|
|
## 📁 Project Structure
|
|
|
|
```
|
|
.
|
|
├── backend/
|
|
│ ├── api/ # REST API endpoints
|
|
│ ├── config/ # Configuration files
|
|
│ ├── db/ # TinyDB / MongoDB persistence layer
|
|
│ ├── events/ # SSE event system
|
|
│ ├── models/ # Data models
|
|
│ ├── tests/ # Backend tests
|
|
│ └── utils/ # Utilities (scheduler, etc)
|
|
├── frontend/
|
|
│ └── src/
|
|
│ ├── common/ # Shared utilities
|
|
│ ├── components/ # Vue components
|
|
│ └── layout/ # Layout components
|
|
└── .github/
|
|
└── specs/ # Feature specifications
|
|
```
|
|
|
|
## 🛠️ Development
|
|
|
|
For detailed development patterns and conventions, see [`.github/copilot-instructions.md`](.github/copilot-instructions.md).
|
|
|
|
## 📚 References
|
|
|
|
- Reset flow (token validation, JWT invalidation, cross-tab logout sync): [`docs/reset-password-reference.md`](docs/reset-password-reference.md)
|
|
|
|
## 📄 License
|
|
|
|
Private project - All rights reserved.
|