-
Notifications
You must be signed in to change notification settings - Fork 4
API Schemas and Auth.md
REST routes are grouped by resource module under api/. The currently registered routers are:
/asset/author/contact/geospatial/group/lexicon/location/observation/publication/sample/sensor/search/thing/ngwmn
Additional API modules exist in the repo (geothermal, form, collabnet, series, well-inventory) that are currently commented out or not registered.
Pydantic schemas live under schemas/ and follow this pattern:
| Schema Type | Purpose |
|---|---|
Create* |
Create payloads |
Update* |
Patch/update payloads |
*Response |
Response serialization |
Common patterns:
- Validation is handled with field and model validators
- Spatial responses often convert geometry into WKT or GeoJSON-like structures
- Observation schemas normalize timestamps to UTC
- Response schemas frequently compose related data for API convenience
-
Create schemas: Required fields as
<type>, optional fields as<type> | None = None -
Update schemas: All fields optional with
Nonedefault - Response schemas: Explicitly define all return types
- Models inherit from
Baseand includeAutoBaseMixin - Use
ReleaseMixinfor entities that require visibility control - Use
DataProvenanceMixinfor tracking data source methods
Two layers of validation protect the API:
| Layer | Error Code | Description |
|---|---|---|
| Pydantic | 422 |
Format, type, and range validation on incoming JSON |
| Service / DB | 409 |
Logical constraints (e.g., duplicate location names) checked within the service layer |
Never use standard HTTPException directly. Use PydanticStyleException for consistency:
from services.exceptions_helper import PydanticStyleException
raise PydanticStyleException(
status_code=409,
detail=[{
"loc": ["body", "location_name"],
"msg": "Location already exists.",
"type": "duplicate_value"
}]
)core.dependencies defines role-based dependencies:
| Role | Access |
|---|---|
Viewer / AMPViewer
|
Read |
Editor / AMPEditor
|
Update |
Admin / AMPAdmin
|
Create + Delete |
LexiconEditor |
Lexicon write |
LexiconAdmin |
Lexicon admin |
This pattern is visible in router implementations such as location, group, and observation.
- OAuth/OIDC configuration points at Authentik
- JWT verification is handled in
core.permissions - The admin UI uses its own auth provider in
admin/auth.py, but reuses the same JWT verification logic - In non-production mode,
AUTHENTIK_DISABLE_AUTHENTICATION=1allows bypass behavior
| Surface | URL | Notes |
|---|---|---|
| Public schema | default /openapi.json
|
Filtered to routes marked public_route
|
| Authenticated schema | /openapi-auth.json |
Full schema |
| Authenticated Swagger | /docs-auth |
Configures OAuth PKCE |
The "public" OpenAPI filter is documentation-driven, not a runtime access guarantee. Routes explicitly marked public_route in api/thing.py still depend on viewer_dependency, meaning:
- They appear in the public schema
- They may still require authentication at runtime unless auth is disabled
If truly anonymous access is intended, verify and update the code accordingly.
-
Bulk groundwater upload:
POST /observation/groundwater-level/bulk-upload -
Search:
GET /search— aggregates contacts, things, and assets -
OGC API: pygeoapi provides a parallel geospatial read surface at
/ogcapi, separate from the REST routers -
Geospatial standards: Primary SRID 4326 (WGS84); geometry stored as
Geometry(POINT, 4326); spatial queries useST_Distance,ST_Within,ST_GeomFromText