# 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*