7.5 KiB
7.5 KiB
TJWater ServerBinary - Quick Reference for Secondary Development
1️⃣ Adding a New API Endpoint (30 seconds)
File: app/api/v1/endpoints/my_feature.py
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)
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
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)
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
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
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
from app.core.encryption import get_encryptor
encryptor = get_encryptor()
encrypted = encryptor.encrypt("secret_password")
decrypted = encryptor.decrypt(encrypted)
Verify Password
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
SECRET_KEY=your-secret-key
ENCRYPTION_KEY=your-fernet-key
DB_HOST=localhost
DB_PORT=5432
Use in Code
from app.core.config import settings
db_url = settings.SQLALCHEMY_DATABASE_URI
token_minutes = settings.ACCESS_TOKEN_EXPIRE_MINUTES
7️⃣ Testing
# 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
# 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
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
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
from app.services.simulation import run_simulation
result = await run_simulation(
project_name="szh",
duration=3600,
time_step=60
)
Audit Operation
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
-
Always use
Depends()for injecting repositories, users# ✅ Right async def endpoint(user: UserInDB = Depends(get_current_active_user)): # ❌ Wrong async def endpoint(user: UserInDB): -
Use parametrized queries to prevent SQL injection
# ✅ Right await cur.execute("SELECT * FROM users WHERE id = %s", (user_id,)) # ❌ Wrong await cur.execute(f"SELECT * FROM users WHERE id = {user_id}") -
Async/await required for database operations
# ✅ Right user = await user_repo.get_user_by_id(1) # ❌ Wrong user = user_repo.get_user_by_id(1) # Missing await -
Role hierarchy for permission checks
# 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