Initial commit: WealthWise financial analytics platform
This commit is contained in:
270
backend/README.md
Normal file
270
backend/README.md
Normal file
@@ -0,0 +1,270 @@
|
||||
# WealthWise Backend
|
||||
|
||||
Production-grade FastAPI backend for WealthWise financial analytics platform with self-hosted authentication.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
- Python 3.11+
|
||||
- Poetry 1.7+
|
||||
- Docker & Docker Compose (recommended)
|
||||
- PostgreSQL 15+
|
||||
|
||||
### Option 1: Docker Compose (Recommended)
|
||||
|
||||
The easiest way to get started with both database and backend:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
|
||||
# Copy environment template
|
||||
cp .env.example .env
|
||||
|
||||
# Start all services (database + backend)
|
||||
docker-compose up -d
|
||||
|
||||
# View logs
|
||||
docker-compose logs -f backend
|
||||
|
||||
# Stop services
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
The API will be available at:
|
||||
- API Docs: http://localhost:8000/api/v1/docs
|
||||
- Health Check: http://localhost:8000/api/v1/health
|
||||
|
||||
### Option 2: Local Development with Docker Database
|
||||
|
||||
1. **Start the database:**
|
||||
```bash
|
||||
docker-compose up -d db
|
||||
```
|
||||
|
||||
2. **Install dependencies:**
|
||||
```bash
|
||||
poetry install
|
||||
```
|
||||
|
||||
3. **Set up environment:**
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Edit .env if needed (default should work with Docker DB)
|
||||
```
|
||||
|
||||
4. **Run database migrations:**
|
||||
```bash
|
||||
# See ALEMBIC.md for detailed instructions
|
||||
poetry run alembic upgrade head
|
||||
```
|
||||
|
||||
5. **Run the server:**
|
||||
```bash
|
||||
poetry run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
## Authentication System
|
||||
|
||||
WealthWise uses self-hosted JWT-based authentication with OAuth2 Password Flow.
|
||||
|
||||
### Registration
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/auth/register \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "user@wealthwise.app",
|
||||
"password": "securepassword123"
|
||||
}'
|
||||
```
|
||||
|
||||
### Login
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/auth/token \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
-d "username=user@wealthwise.app&password=securepassword123"
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"access_token": "eyJhbGciOiJIUzI1NiIs...",
|
||||
"token_type": "bearer"
|
||||
}
|
||||
```
|
||||
|
||||
### Access Protected Endpoint
|
||||
|
||||
```bash
|
||||
curl -X GET http://localhost:8000/api/v1/users/me \
|
||||
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
|
||||
```
|
||||
|
||||
### Using Swagger UI
|
||||
|
||||
1. Open http://localhost:8000/api/v1/docs
|
||||
2. Click "Authorize" button (top right)
|
||||
3. Enter: `Bearer <your-token>` (replace with actual token)
|
||||
4. Or use the `/auth/token` endpoint to get a token, then use it
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
poetry run pytest
|
||||
|
||||
# Run with coverage
|
||||
poetry run pytest --cov=app --cov-report=html
|
||||
|
||||
# Run specific test file
|
||||
poetry run pytest tests/test_auth.py -v
|
||||
|
||||
# Run auth tests only
|
||||
poetry run pytest tests/test_auth.py -v
|
||||
```
|
||||
|
||||
## Database Migrations
|
||||
|
||||
See [ALEMBIC.md](ALEMBIC.md) for detailed migration instructions.
|
||||
|
||||
Quick commands:
|
||||
```bash
|
||||
# Create migration
|
||||
poetry run alembic revision --autogenerate -m "Description"
|
||||
|
||||
# Apply migrations
|
||||
poetry run alembic upgrade head
|
||||
|
||||
# View history
|
||||
poetry run alembic history
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
backend/
|
||||
├── app/
|
||||
│ ├── api/
|
||||
│ │ ├── v1/
|
||||
│ │ │ ├── endpoints/
|
||||
│ │ │ │ ├── auth.py # Authentication endpoints
|
||||
│ │ │ │ ├── health.py # Health check endpoint
|
||||
│ │ │ │ └── users.py # User endpoints
|
||||
│ │ │ └── api.py # Router aggregation
|
||||
│ │ └── deps.py # Dependencies (DB session, auth)
|
||||
│ ├── core/
|
||||
│ │ ├── config.py # Settings management
|
||||
│ │ ├── db.py # Database engine & sessions
|
||||
│ │ └── security.py # Password hashing & JWT utilities
|
||||
│ ├── models/
|
||||
│ │ ├── __init__.py # Model exports
|
||||
│ │ ├── base.py # Base SQLModel classes
|
||||
│ │ ├── user.py # User model
|
||||
│ │ ├── portfolio.py # Portfolio model
|
||||
│ │ └── transaction.py # Transaction model
|
||||
│ ├── schemas/
|
||||
│ │ ├── __init__.py # Schema exports
|
||||
│ │ ├── token.py # Token schemas (legacy Supabase)
|
||||
│ │ └── user.py # User schemas
|
||||
│ └── main.py # FastAPI application factory
|
||||
├── tests/ # Test suite
|
||||
├── pyproject.toml # Poetry configuration
|
||||
├── Dockerfile # Multi-stage build
|
||||
├── docker-compose.yml # Docker Compose services
|
||||
├── .env.example # Environment template
|
||||
├── README.md # This file
|
||||
└── ALEMBIC.md # Migration guide
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
See `.env.example` for all available configuration options.
|
||||
|
||||
### Required Variables
|
||||
- `DATABASE_URL`: PostgreSQL connection string
|
||||
- Local Docker: `postgresql+asyncpg://postgres:postgres@localhost:5432/wealthwise`
|
||||
- Production: `postgresql+asyncpg://user:pass@host:5432/dbname`
|
||||
- `SECRET_KEY`: JWT signing secret (generate with `openssl rand -hex 32`)
|
||||
- `ALGORITHM`: JWT algorithm (default: HS256)
|
||||
- `ACCESS_TOKEN_EXPIRE_MINUTES`: Token expiration (default: 30)
|
||||
|
||||
### Docker Compose Configuration
|
||||
The docker-compose.yml sets up:
|
||||
- PostgreSQL 15 with persistent volume
|
||||
- FastAPI backend with hot reload
|
||||
- Health checks for both services
|
||||
- Shared network for service communication
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Authentication
|
||||
- `POST /api/v1/auth/register` - Register new user
|
||||
- `POST /api/v1/auth/token` - Login (OAuth2 Password Flow)
|
||||
|
||||
### Users (Protected)
|
||||
- `GET /api/v1/users/me` - Get current user info
|
||||
- `GET /api/v1/users/me/active` - Get current active user
|
||||
|
||||
### Health Check
|
||||
- `GET /api/v1/health` - Comprehensive health check with DB connectivity
|
||||
- `GET /api/v1/health/ready` - Kubernetes readiness probe
|
||||
- `GET /api/v1/health/live` - Kubernetes liveness probe
|
||||
|
||||
### Documentation
|
||||
- `GET /api/v1/docs` - Swagger UI
|
||||
- `GET /api/v1/redoc` - ReDoc UI
|
||||
- `GET /api/v1/openapi.json` - OpenAPI specification
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
### Adding New Endpoints
|
||||
1. Create endpoint file in `app/api/v1/endpoints/`
|
||||
2. Add router to `app/api/v1/api.py`
|
||||
3. Write tests in `tests/`
|
||||
|
||||
### Database Models
|
||||
1. Inherit from `BaseModel` in `app/models/base.py`
|
||||
2. Use SQLModel for type-safe ORM operations
|
||||
3. Create migration after model changes: `poetry run alembic revision --autogenerate -m "Description"`
|
||||
|
||||
### Authentication in Endpoints
|
||||
|
||||
```python
|
||||
from fastapi import APIRouter, Depends
|
||||
from app.api.deps import get_current_user
|
||||
from app.models import User
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/protected")
|
||||
async def protected_route(current_user: User = Depends(get_current_user)):
|
||||
return {"message": f"Hello {current_user.email}"}
|
||||
```
|
||||
|
||||
### Code Quality
|
||||
- Format with Black: `poetry run black app tests`
|
||||
- Import sort with isort: `poetry run isort app tests`
|
||||
- Type check with mypy: `poetry run mypy app`
|
||||
|
||||
## Security Notes
|
||||
|
||||
- **Passwords**: Hashed using bcrypt (12 rounds by default)
|
||||
- **JWT Tokens**: HS256 algorithm, 30-minute expiration by default
|
||||
- **SECRET_KEY**: Must be changed in production! Use a strong random key.
|
||||
- **HTTPS**: Always use HTTPS in production to protect tokens
|
||||
- **CORS**: Configure CORS_ORIGINS to only allow your frontend domain
|
||||
|
||||
## Migration from Supabase
|
||||
|
||||
This backend has been migrated from Supabase Auth to self-hosted authentication:
|
||||
|
||||
- ✅ JWT validation uses local `SECRET_KEY` instead of Supabase
|
||||
- ✅ Password hashing with bcrypt
|
||||
- ✅ OAuth2 Password Flow endpoints
|
||||
- ✅ User, Portfolio, and Transaction models
|
||||
- ✅ Docker Compose for local development
|
||||
|
||||
## License
|
||||
|
||||
Private - WealthWise Financial Technologies
|
||||
Reference in New Issue
Block a user