This is as a realtime quey API for any entity that want's to get CSD data. Built on FASTAPI, a lightweight Python API framework.
- β‘ FastAPI
- π§° SQLAlchemy V2 for the Python SQL database interactions (ORM).
- π Pydantic, used by FastAPI, for the data validation and settings management.
- πΎ PostgreSQL as the SQL database.
- π JWT Authentication - JSON Web Token based authentication
- π Docker Compose for optional containerized development and builds (the app can also be run directly on the host; see below)
- β Tests with Pytest.
- π CI (continuous integration) and CD (continuous deployment) based on GitHub Actions.
- User authentication with JWT tokens
- Role-based access control (superuser and regular users)
- Full CRUD operations for users and items
- Secure password hashing
- Email uniqueness validation
- Self-service user management
- Administrative user management
- Item ownership and permissions
- Async database operations
- Input validation and error handling
You can then update configs in the .env files to customize your configurations.
Before deploying it, make sure you change at least the values for:
POSTGRES_PASSWORD
You can (and should) pass these as environment variables from secrets
You can run the API and Alembic on your machine with a PostgreSQL instance you provide (local install, managed service, or Postgres only in Docker).
- Python 3.12
- PostgreSQL (16 or newer is a good match for the Docker image in
compose.yaml)
From the repository root:
python -m venv .venvActivate the virtual environment:
- Linux or macOS:
source .venv/bin/activate - Windows (PowerShell):
.venv\Scripts\Activate.ps1
Install dependencies:
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pip install -r requirements-dev.txtThe second requirements file is optional for running the API alone; include it for tests, linting, and other dev tooling.
Create an empty database (and role, if needed) that matches the values you will put in .env. Copy .env.example to .env at the repository root and set at least POSTGRES_*, SECRET_KEY, FIRST_SUPERUSER, and FIRST_SUPERUSER_PASSWORD as described in Configure.
For PostgreSQL on the same machine using the default port, use POSTGRES_SERVER=localhost and POSTGRES_PORT=5432.
Settings load the root .env when commands are run with a working directory of src (see app/core/config.py).
Alembic and Uvicorn expect the working directory to be src so the app package and alembic.ini resolve correctly (this mirrors the layout under /usr/src in the container).
cd src
alembic upgrade head
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000Then open the interactive docs at http://localhost:8000/docs (ReDoc: http://localhost:8000/redoc).
To install and configure ocpo-api as a Windows service using NSSM, see docs/nssm-windows-service.md.
If you want Docker only for the database, start the dev database service and leave the API on the host:
docker compose --profile dev up db-dev -dWith the default port mapping in compose.yaml, Postgres is available on the host at localhost:8081. Point .env at it with POSTGRES_SERVER=localhost, POSTGRES_PORT=8081, and the same POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB values your Compose stack uses. Then run the Python steps above from src.
With requirements-dev.txt installed and PostgreSQL reachable using the connection details in .env, from src run:
cd src
python -m pytestThe test suite configures the engine from the same settings as the app and, for the session-scoped engine fixture, drops and recreates tables in that database. Use a dedicated database (for example a separate POSTGRES_DB value in .env while testing) or keep using ./scripts/test-local.sh, which runs tests against an isolated Compose profile.
To run the API as a Windows service with NSSM (including use of the repository run_api.bat wrapper for PYTHONPATH and the virtualenv), see docs/nssm-windows-service.md.
If requirements change build a new base image
docker buildx build -f Dockerfile.base -t ocl_base_image:latest .
Start the stack with Docker Compose:
./scripts/dev-local.shTo seed data into the db. (Make sure to change the SEED_FILE variable in your .env)
# Option 1 (CLI): copy the XLSX into the running container, then run the seeder
docker cp "Incident_DATA.xlsx" ocl-api-oag-api-dev-1:/usr/src/Incident_DATA.xlsx
docker exec -it ocl-api-oag-api-dev-1 python -m app.seed_incident_db --file "/usr/src/Incident_DATA.xlsx"
Alternatively (recommended for non-technical users), upload the monthly XLSX and seed via the API:
- Swagger: open
/docson the same base URL you use for the API (for examplehttp://localhost:8000/docswithout Docker, or the host port fromcompose.yamlwith Docker) βPOST /api/v1/incidents/seed - curl (replace the base URL and port to match your setup):
curl -X POST "http://localhost:8000/api/v1/incidents/seed" \
-H "Authorization: Bearer <access_token>" \
-F "file=@Incident_DATA.xlsx"
This will:
- Build the API container
- Start PostgreSQL
- Set up the database
- Start the FastAPI server
Execute the test suite:
./scripts/test-local.shThis will:
- Set up a test database
- Run the pytest suite
The project includes:
- Unit tests for CRUD operations
- Integration tests for API endpoints
- Fixture-based test setup
- Transaction rollback for test isolation
- Async test support
Once running, access the interactive API documentation at:
- Without Docker (Uvicorn on port 8000 as above): Swagger UI at
http://localhost:8000/docs, ReDoc athttp://localhost:8000/redoc - With Docker Compose: use the host port mapped to the API container in
compose.yaml(for example8085βhttp://localhost:8085/docs)
.
βββ Dockerfile # Main Dockerfile for the application
βββ Dockerfile.base # Base Dockerfile for common dependencies
βββ README.md # Project documentation
βββ compose.yaml # Docker Compose configuration
βββ development.md # Development guidelines and setup
βββ requirements-dev.txt # Development dependencies
βββ requirements.txt # Production dependencies
βββ scripts/ # Utility scripts
β βββ create_alembic_revision.sh # Database migration script
β βββ dev-local.sh # Local development startup
β βββ test-local.sh # Test execution script
βββ src/ # Source code root
βββ alembic.ini # Alembic configuration
βββ app/ # Main application package
βββ alembic/ # Database migrations
β βββ README
β βββ env.py
β βββ script.py.mako
β βββ versions/
βββ api/ # API layer
β βββ deps.py # FastAPI dependencies
β βββ main.py # API configuration
β βββ routes/ # API endpoints
β βββ items.py # Item endpoints
β βββ login.py # Authentication endpoints
β βββ users.py # User endpoints
β βββ utils.py # Route utilities
βββ core/ # Core functionality
β βββ config.py # Application configuration
β βββ db.py # Database connection
β βββ security.py # Security utilities
βββ crud/ # Database operations
β βββ base.py # Base CRUD operations
β βββ items.py # Item CRUD operations
β βββ users.py # User CRUD operations
βββ main.py # Application entry point
βββ models/ # Data models
β βββ api/ # API models (Pydantic)
β β βββ generic.py
β β βββ items.py
β β βββ users.py
β βββ db/ # Database models (SQLAlchemy)
β βββ base.py
β βββ items.py
β βββ users.py
βββ pytest.ini # Pytest configuration
βββ tests/ # Test suite
β βββ api/ # API tests
β β βββ routes/
β β βββ test_items.py
β β βββ test_login.py
β β βββ test_users.py
β βββ conftest.py # Test fixtures
β βββ crud/ # CRUD tests
β β βββ test_item.py
β β βββ test_user.py
β βββ utils/ # Test utilities
β βββ item.py
β βββ user.py
β βββ utils.py
βββ utils.py # General utilities