327 lines
7.5 KiB
Markdown
327 lines
7.5 KiB
Markdown
# TJWater ServerBinary - Quick Reference for Secondary Development
|
|
|
|
## 1️⃣ Adding a New API Endpoint (30 seconds)
|
|
|
|
### File: `app/api/v1/endpoints/my_feature.py`
|
|
```python
|
|
from fastapi import APIRouter, Depends
|
|
from app.auth.dependencies import get_current_active_user
|
|
from app.domain.schemas.user import UserInDB
|
|
|
|
router = APIRouter()
|
|
|
|
@router.get("/list")
|
|
async def list_items(user: UserInDB = Depends(get_current_active_user)):
|
|
return {"items": []}
|
|
|
|
@router.post("/create")
|
|
async def create_item(data: dict, user: UserInDB = Depends(get_current_active_user)):
|
|
return {"status": "created"}
|
|
```
|
|
|
|
### File: `app/api/v1/router.py` (Add 2 lines)
|
|
```python
|
|
from app.api.v1.endpoints import my_feature
|
|
|
|
api_router.include_router(my_feature.router, prefix="/items", tags=["Items"])
|
|
```
|
|
|
|
**Done!** Endpoint available at `POST /api/v1/items/create`
|
|
|
|
---
|
|
|
|
## 2️⃣ Database Query Pattern
|
|
|
|
### Using Repository
|
|
```python
|
|
from app.infra.repositories.user_repository import UserRepository
|
|
from app.auth.dependencies import get_user_repository
|
|
|
|
@router.get("/user/{user_id}")
|
|
async def get_user(user_id: int, user_repo: UserRepository = Depends(get_user_repository)):
|
|
user = await user_repo.get_user_by_id(user_id)
|
|
return user
|
|
```
|
|
|
|
### Direct Query (if no repository exists)
|
|
```python
|
|
async with db.get_connection() as conn:
|
|
async with conn.cursor() as cur:
|
|
await cur.execute("SELECT * FROM users WHERE id = %s", (user_id,))
|
|
row = await cur.fetchone()
|
|
return dict(row) if row else None
|
|
```
|
|
|
|
---
|
|
|
|
## 3️⃣ Role-Based Access Control
|
|
|
|
```python
|
|
from app.auth.permissions import require_admin, require_role
|
|
from app.domain.models.role import UserRole
|
|
|
|
# Admin only
|
|
@router.delete("/users/{user_id}")
|
|
async def delete_user(user_id: int, admin: UserInDB = Depends(require_admin)):
|
|
pass
|
|
|
|
# Operator or higher
|
|
@router.post("/projects/")
|
|
async def create_project(user: UserInDB = Depends(require_role(UserRole.OPERATOR))):
|
|
pass
|
|
|
|
# Custom role check
|
|
def require_viewer():
|
|
return require_role(UserRole.VIEWER)
|
|
|
|
@router.get("/reports")
|
|
async def get_reports(user: UserInDB = Depends(require_viewer)):
|
|
pass
|
|
```
|
|
|
|
---
|
|
|
|
## 4️⃣ Call Native (Binary) Code
|
|
|
|
```python
|
|
from app.native.wndb import get_all_junctions, add_junction, set_junction
|
|
|
|
# Read network elements
|
|
junctions = get_all_junctions()
|
|
|
|
# Create
|
|
add_junction({"id": "J1", "x": 0.0, "y": 0.0, "demand": 100.0})
|
|
|
|
# Update
|
|
set_junction("J1", {"demand": 150.0})
|
|
|
|
# Get constants
|
|
from app.native.wndb import PIPE_STATUS_OPEN, OPTION_UNITS_LPS
|
|
```
|
|
|
|
---
|
|
|
|
## 5️⃣ Encryption & Security
|
|
|
|
### Encrypt Sensitive Data
|
|
```python
|
|
from app.core.encryption import get_encryptor
|
|
|
|
encryptor = get_encryptor()
|
|
|
|
encrypted = encryptor.encrypt("secret_password")
|
|
decrypted = encryptor.decrypt(encrypted)
|
|
```
|
|
|
|
### Verify Password
|
|
```python
|
|
from app.core.security import verify_password, get_password_hash
|
|
|
|
# When creating user
|
|
hashed = get_password_hash(user.password)
|
|
|
|
# When checking login
|
|
if verify_password(form_data.password, stored_hash):
|
|
# Correct password
|
|
pass
|
|
```
|
|
|
|
---
|
|
|
|
## 6️⃣ Configuration
|
|
|
|
### In `.env` file
|
|
```bash
|
|
SECRET_KEY=your-secret-key
|
|
ENCRYPTION_KEY=your-fernet-key
|
|
DB_HOST=localhost
|
|
DB_PORT=5432
|
|
```
|
|
|
|
### Use in Code
|
|
```python
|
|
from app.core.config import settings
|
|
|
|
db_url = settings.SQLALCHEMY_DATABASE_URI
|
|
token_minutes = settings.ACCESS_TOKEN_EXPIRE_MINUTES
|
|
```
|
|
|
|
---
|
|
|
|
## 7️⃣ Testing
|
|
|
|
```python
|
|
# tests/unit/test_my_feature.py
|
|
import pytest
|
|
|
|
def test_my_function():
|
|
result = my_function()
|
|
assert result == expected
|
|
|
|
# Run tests
|
|
pytest tests/ -v
|
|
pytest tests/unit/test_my_feature.py::test_my_function -v
|
|
```
|
|
|
|
---
|
|
|
|
## 🗺️ Directory Quick Map
|
|
|
|
| Path | What | Use For |
|
|
|------|------|---------|
|
|
| `app/api/v1/endpoints/` | API routes | Add new endpoints |
|
|
| `app/auth/` | Auth logic | Login, permissions |
|
|
| `app/domain/` | Models/Schemas | Data structures |
|
|
| `app/infra/db/` | DB access | Queries, repositories |
|
|
| `app/services/` | Business logic | Complex operations |
|
|
| `app/native/wndb/` | Binary functions | Network simulation |
|
|
| `app/core/` | Core utilities | Config, security, encryption |
|
|
| `tests/` | Tests | Unit & integration tests |
|
|
|
|
---
|
|
|
|
## 🔑 Key Imports
|
|
|
|
```python
|
|
# Authentication
|
|
from app.auth.dependencies import get_current_active_user, get_user_repository
|
|
from app.auth.permissions import require_admin, require_role
|
|
|
|
# Database
|
|
from app.infra.db.postgresql.database import db, get_database_instance
|
|
from app.infra.repositories.user_repository import UserRepository
|
|
|
|
# Schemas & Models
|
|
from app.domain.schemas.user import UserInDB, UserCreate, Token
|
|
from app.domain.models.role import UserRole
|
|
|
|
# Security
|
|
from app.core.security import create_access_token, verify_password, get_password_hash
|
|
from app.core.encryption import get_encryptor
|
|
|
|
# Config
|
|
from app.core.config import settings
|
|
|
|
# Native API
|
|
from app.native.wndb import get_all_junctions, add_junction, open_project
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 Common Tasks
|
|
|
|
### Register New User
|
|
```python
|
|
from app.infra.repositories.user_repository import UserRepository
|
|
from app.domain.schemas.user import UserCreate
|
|
from app.domain.models.role import UserRole
|
|
|
|
user_data = UserCreate(
|
|
username="john",
|
|
email="john@example.com",
|
|
password="securepass",
|
|
role=UserRole.USER
|
|
)
|
|
new_user = await user_repo.create_user(user_data)
|
|
```
|
|
|
|
### Query Database
|
|
```python
|
|
async with db.get_connection() as conn:
|
|
async with conn.cursor() as cur:
|
|
await cur.execute("SELECT * FROM users LIMIT 10")
|
|
rows = await cur.fetchall()
|
|
return [dict(r) for r in rows]
|
|
```
|
|
|
|
### Run Simulation
|
|
```python
|
|
from app.services.simulation import run_simulation
|
|
|
|
result = await run_simulation(
|
|
project_name="szh",
|
|
duration=3600,
|
|
time_step=60
|
|
)
|
|
```
|
|
|
|
### Audit Operation
|
|
```python
|
|
from app.core.audit import log_audit_event, AuditAction
|
|
|
|
await log_audit_event(
|
|
action=AuditAction.CREATE,
|
|
resource_type="pipe",
|
|
resource_id="P1",
|
|
actor_id=user.id,
|
|
details={"diameter": 100, "material": "PVC"}
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## ⚠️ Common Gotchas
|
|
|
|
1. **Always use `Depends()`** for injecting repositories, users
|
|
```python
|
|
# ✅ Right
|
|
async def endpoint(user: UserInDB = Depends(get_current_active_user)):
|
|
|
|
# ❌ Wrong
|
|
async def endpoint(user: UserInDB):
|
|
```
|
|
|
|
2. **Use parametrized queries** to prevent SQL injection
|
|
```python
|
|
# ✅ Right
|
|
await cur.execute("SELECT * FROM users WHERE id = %s", (user_id,))
|
|
|
|
# ❌ Wrong
|
|
await cur.execute(f"SELECT * FROM users WHERE id = {user_id}")
|
|
```
|
|
|
|
3. **Async/await** required for database operations
|
|
```python
|
|
# ✅ Right
|
|
user = await user_repo.get_user_by_id(1)
|
|
|
|
# ❌ Wrong
|
|
user = user_repo.get_user_by_id(1) # Missing await
|
|
```
|
|
|
|
4. **Role hierarchy** for permission checks
|
|
```python
|
|
# All levels include higher permissions
|
|
VIEWER (1) < USER (2) < OPERATOR (3) < ADMIN (4)
|
|
```
|
|
|
|
---
|
|
|
|
## 📞 File Locations Reference
|
|
|
|
- **Main app entry**: `app/main.py` (83 lines)
|
|
- **Central router**: `app/api/v1/router.py` (98 lines)
|
|
- **Config**: `app/core/config.py` (82 lines)
|
|
- **Auth dependencies**: `app/auth/dependencies.py`
|
|
- **Permissions**: `app/auth/permissions.py`
|
|
- **Database**: `app/infra/db/postgresql/database.py`
|
|
- **Repositories**: `app/infra/repositories/`
|
|
- **Schemas**: `app/domain/schemas/`
|
|
- **Models**: `app/domain/models/`
|
|
|
|
---
|
|
|
|
## 📚 Full Documentation
|
|
|
|
See **SECONDARY_DEVELOPMENT_GUIDE.md** for comprehensive guide on:
|
|
- Architecture overview
|
|
- Detailed endpoint creation
|
|
- Database patterns
|
|
- Native module integration
|
|
- Testing setup
|
|
- Deployment
|
|
|
|
---
|
|
|
|
*Generated for TJWater ServerBinary secondary development team*
|