更新文档
This commit is contained in:
@@ -0,0 +1,326 @@
|
||||
# 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.api 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.api 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/api/` | 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.api 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*
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user