diff --git a/README.md b/README.md index b0217c3..97a5226 100644 --- a/README.md +++ b/README.md @@ -13,14 +13,14 @@ faculties can adapt the platform to their own campuses. The solution comprises five collaborating layers: -- **IoT layer** – ESP32-based sensor nodes send telemetry to a lightweight Flask +- **IoT layer** - ESP32-based sensor nodes send telemetry to a lightweight Flask logger (`iot/logging`). -- **Backend APIs** – A FastAPI service (`backend/app`) exposes CRUD endpoints for +- **Backend APIs** - A FastAPI service (`backend/app`) exposes CRUD endpoints for projects, resources, locations, maintenance tickets, and sensor sites. -- **GIS & Analytics** – Future modules will combine telemetry and asset data to +- **GIS & Analytics** - Future modules will combine telemetry and asset data to power dashboards and risk assessments. -- **Frontend** – Web dashboards and mobile apps consume the backend APIs. -- **Deployment** – Infrastructure-as-code scripts will package the stack for on +- **Frontend** - Web dashboards and mobile apps consume the backend APIs. +- **Deployment** - Infrastructure-as-code scripts will package the stack for on campus or cloud hosting. Consult `docs/backend_crud_plan.md` for the architectural rationale that guided @@ -28,12 +28,16 @@ issue `#5` (CRUD API implementation). ### Module Overview -- `iot/` – Firmware sketches and logging scripts for field sensors. -- `backend/` – FastAPI application, domain models, services, and tests. -- `docs/` – Supplemental guides and design notes. +- `iot/` - Firmware sketches and logging scripts for field sensors. +- `backend/` - FastAPI application, domain models, services, and tests. +- `docs/` - Supplemental guides and design notes. - Additional directories (frontend, gis, deployment) will be filled as the broader initiative matures. +Backend-specific onboarding now lives in [`backend/README.md`](backend/README.md) +and the centralized endpoint reference is documented in +[`docs/API_REFERENCE.md`](docs/API_REFERENCE.md). + ## Backend Service (Issue #5 Deliverable) ### Prerequisites @@ -122,8 +126,9 @@ institutional context. ## License -MIT, Apache +License is not yet specified. The README currently lists "MIT, Apache", which is ambiguous. Please add a LICENSE file to clarify the intended license. ## Maintainers Muwanga Erasto Kosea, Ouma Ronald + diff --git a/backend/.env.example b/backend/.env.example index 19960b3..9da4e3f 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -1,6 +1,14 @@ # Default configuration for local development. + +# Async SQLAlchemy connection string used by the backend services. LIFELINE_DATABASE_URL=sqlite+aiosqlite:///./lifeline.db + +# Version string exposed in the FastAPI metadata and OpenAPI docs. LIFELINE_API_VERSION=0.1.0 + +# Contact shown in the generated API documentation. LIFELINE_CONTACT_EMAIL=ict-support@lifeline.example.edu + +# Default and maximum page sizes for list endpoints. LIFELINE_PAGINATION_DEFAULT_LIMIT=20 LIFELINE_PAGINATION_MAX_LIMIT=100 diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 0000000..24cfaf5 --- /dev/null +++ b/backend/README.md @@ -0,0 +1,108 @@ +# LifeLine-ICT Backend Setup + +This guide focuses on the FastAPI backend located in `backend/`. + +## Prerequisites + +- Python 3.11+ +- `pip` +- Optional: a virtual environment tool such as `venv` + +## Local Setup + +From the `backend/` directory: + +```bash +python -m venv .venv +``` + +Activate the environment: + +```bash +# Windows PowerShell +.venv\Scripts\Activate.ps1 + +# Linux or macOS +source .venv/bin/activate +``` + +Install dependencies: + +```bash +pip install -r requirements.txt +``` + +## Environment Variables + +Copy the sample configuration before running the app: + +```bash +cp .env.example .env +``` + +If you are using PowerShell on Windows, the equivalent command is: + +```powershell +Copy-Item .env.example .env +``` + +### Key Settings + +- `LIFELINE_DATABASE_URL`: async database URL used by SQLAlchemy +- `LIFELINE_API_VERSION`: version shown in the FastAPI docs +- `LIFELINE_CONTACT_EMAIL`: support contact displayed in OpenAPI metadata +- `LIFELINE_PAGINATION_DEFAULT_LIMIT`: default list size for collection endpoints +- `LIFELINE_PAGINATION_MAX_LIMIT`: upper bound accepted by pagination params + +The default sample config uses local SQLite, which is enough for first-time +setup and classroom development. + +## Database Migrations + +Run migrations from the `backend/` directory: + +```bash +alembic upgrade head +``` + +Create a new migration when models change: + +```bash +alembic revision --autogenerate -m "describe_change" +``` + +## Running the API + +If you are inside `backend/`, start the development server with: + +```bash +uvicorn app.main:app --reload +``` + +Useful endpoints after startup: + +- Swagger UI: `http://127.0.0.1:8000/docs` +- ReDoc: `http://127.0.0.1:8000/redoc` +- App health: `http://127.0.0.1:8000/health` + +## Running Tests + +From the repository root: + +```bash +pytest backend/tests +``` + +If you are already inside `backend/`, run: + +```bash +pytest tests +``` + +## Optional Seed Data + +Populate sample data for demos or manual testing: + +```bash +python scripts/seed_sample_data.py +``` diff --git a/docs/API_REFERENCE.md b/docs/API_REFERENCE.md new file mode 100644 index 0000000..cd07b1d --- /dev/null +++ b/docs/API_REFERENCE.md @@ -0,0 +1,235 @@ +# LifeLine-ICT API Reference + +This document is the centralized reference for the currently implemented +backend routes. It complements the live FastAPI docs at +`http://127.0.0.1:8000/docs`. + +## Base URLs + +- Local API root: `http://127.0.0.1:8000` +- Versioned API prefix: `http://127.0.0.1:8000/api/v1` + +## Authentication + +### Create a user + +`POST /api/v1/auth/users` + +The auth routes use `OAuth2PasswordRequestForm`, so credentials are sent as form +fields rather than JSON. + +```bash +curl -X POST http://127.0.0.1:8000/api/v1/auth/users \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "username=demo-admin&password=change-me" +``` + +### Obtain a bearer token + +`POST /api/v1/auth/token` + +```bash +curl -X POST http://127.0.0.1:8000/api/v1/auth/token \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "username=demo-admin&password=change-me" +``` + +Example response: + +```json +{ + "access_token": "eyJhbGciOi...", + "token_type": "bearer" +} +``` + +### Protected routes + +The CRUD routers are wired with a bearer-token dependency. Send the token using: + +```text +Authorization: Bearer +``` + +Role-based restrictions are not yet implemented in the current source tree, so +the present auth model is authenticated-user access rather than role-scoped +access. + +## Shared Query Parameters + +Collection endpoints accept these optional query parameters: + +| Parameter | Description | +| --- | --- | +| `limit` | Number of records to return | +| `offset` | Zero-based starting position | +| `search` | Case-insensitive free-text filter | + +Paginated responses use this envelope: + +```json +{ + "data": [], + "pagination": { + "total": 0, + "limit": 20, + "offset": 0 + } +} +``` + +## Health and Utility Endpoints + +| Method | Path | Purpose | +| --- | --- | --- | +| `GET` | `/health` | Application availability check | +| `GET` | `/api/v1/analytics/health` | Lightweight analytics module health check | + +## Projects + +| Method | Path | +| --- | --- | +| `GET` | `/api/v1/projects` | +| `GET` | `/api/v1/projects/{project_id}` | +| `POST` | `/api/v1/projects` | +| `PUT` | `/api/v1/projects/{project_id}` | +| `PATCH` | `/api/v1/projects/{project_id}` | +| `DELETE` | `/api/v1/projects/{project_id}` | + +Example create payload: + +```json +{ + "name": "Campus Network Upgrade", + "description": "Upgrade backbone links for the main campus.", + "status": "planned", + "sponsor": "ICT Directorate", + "start_date": "2026-04-29", + "end_date": "2026-08-29", + "primary_contact_email": "ict-directorate@example.edu" +} +``` + +Example response: + +```json +{ + "id": 1, + "name": "Campus Network Upgrade", + "description": "Upgrade backbone links for the main campus.", + "status": "planned", + "sponsor": "ICT Directorate", + "start_date": "2026-04-29", + "end_date": "2026-08-29", + "primary_contact_email": "ict-directorate@example.edu" +} +``` + +## ICT Resources + +| Method | Path | +| --- | --- | +| `GET` | `/api/v1/resources` | +| `GET` | `/api/v1/resources/{resource_id}` | +| `POST` | `/api/v1/resources` | +| `PUT` | `/api/v1/resources/{resource_id}` | +| `PATCH` | `/api/v1/resources/{resource_id}` | +| `DELETE` | `/api/v1/resources/{resource_id}` | + +Required fields for create and full update: + +- `name` +- `category` +- `lifecycle_state` + +Optional linkage fields: + +- `project_id` +- `location_id` + +## Locations + +| Method | Path | +| --- | --- | +| `GET` | `/api/v1/locations` | +| `GET` | `/api/v1/locations/{location_id}` | +| `POST` | `/api/v1/locations` | +| `PUT` | `/api/v1/locations/{location_id}` | +| `PATCH` | `/api/v1/locations/{location_id}` | +| `DELETE` | `/api/v1/locations/{location_id}` | + +Example geometry payload: + +```json +{ + "campus": "Main Campus", + "building": "ICT Block", + "room": "Lab 2", + "geom": { + "lat": 0.3476, + "lon": 32.5825 + } +} +``` + +## Maintenance Tickets + +| Method | Path | +| --- | --- | +| `GET` | `/api/v1/maintenance-tickets` | +| `GET` | `/api/v1/maintenance-tickets/{ticket_id}` | +| `POST` | `/api/v1/maintenance-tickets` | +| `PUT` | `/api/v1/maintenance-tickets/{ticket_id}` | +| `PATCH` | `/api/v1/maintenance-tickets/{ticket_id}` | +| `DELETE` | `/api/v1/maintenance-tickets/{ticket_id}` | + +Important fields: + +- `resource_id` +- `reported_by` +- `issue_summary` +- `severity` +- `status` +- `opened_at` + +## Sensor Sites + +| Method | Path | +| --- | --- | +| `GET` | `/api/v1/sensor-sites` | +| `GET` | `/api/v1/sensor-sites/{site_id}` | +| `POST` | `/api/v1/sensor-sites` | +| `PUT` | `/api/v1/sensor-sites/{site_id}` | +| `PATCH` | `/api/v1/sensor-sites/{site_id}` | +| `DELETE` | `/api/v1/sensor-sites/{site_id}` | + +Required fields: + +- `resource_id` +- `data_collection_endpoint` + +Optional fields: + +- `project_id` +- `location_id` +- `notes` + +## Alerts + +| Method | Path | Notes | +| --- | --- | --- | +| `POST` | `/api/v1/alerts` | Parameters are currently accepted as query parameters | +| `GET` | `/api/v1/alerts/{sensor_id}` | Returns alerts for one sensor | + +Example alert creation request: + +```bash +curl -X POST "http://127.0.0.1:8000/api/v1/alerts?sensor_id=3&metric=temperature&value=38.4&threshold=35.0" \ + -H "Authorization: Bearer " +``` + +## Common Error Responses + +- `401 Unauthorized`: Missing or invalid bearer token +- `404 Not Found`: Requested record does not exist +- `422 Unprocessable Entity`: Validation failed for the submitted payload