Files
server/util/SeederApi/README.md
Matt Gibson 2e6bf44504 Add SeederApi PlayData delete scheduled job (#7281)
* Use Quartz-based hosted service to clear old play data

We need to stop possible bloat of databases should users of a seeded data fail to appropriately clean up after themselves.

Using the hosted services present in other projects, this adds an alive job and play data delete job to the SeederApi

* Trigger play data delete frequently enough for dev servers

Development servers are unlikely to be running at midnight UTC, so we need to delete more frequently to ensure data is cleaned up. The Job still deletes things older than a day, it just checks much more frequently, now.

* Fixup sonarqube

* Fixup parallel test issues with jobs hosted services

* Remove alive job and unneeded fixme

* Revert "Remove alive job and unneeded fixme"

This reverts commit 0c10e4a675.

* Simplify alive job

Used the wrong job as a template, the api alive job is much more like what we want.

* Update readme to callout ephemeral data
2026-04-13 09:57:23 -07:00

197 lines
6.1 KiB
Markdown

# SeederApi
A web API for dynamically seeding and querying test data in the Bitwarden database during development and testing.
## Overview
The SeederApi provides HTTP endpoints to execute [Seeder](../Seeder/README.md) scenes and queries, enabling automated test data
generation and retrieval through a RESTful interface. This is particularly useful for integration testing, local
development workflows, and automated test environments.
## Architecture
The SeederApi consists of three main components:
1. **Controllers** - HTTP endpoints for seeding, querying, and managing test data
2. **Services** - Business logic for scene and query execution
3. **Models** - Request/response models for API communication
4. **Jobs** - Scheduled jobs run through JobsHostedService.
### Key Components
- **SeedController** (`/seed`) - Creates and destroys seeded test data
- **QueryController** (`/query`) - Executes read-only queries against existing data
- **InfoController** (`/alive`, `/version`) - Health check and version information
- **SceneService** - Manages scene execution and cleanup with play ID tracking
- **QueryService** - Executes read-only query operations
- **Cleanup Job** - Executes every 15 minutes to delete old play data.
## How To Use
### Starting the API
```bash
cd util/SeederApi
dotnet run
```
The API will start on the configured port (typically `http://localhost:5000`).
### Seeding Data
Send a POST request to `/seed` with a scene template name and optional arguments. Include the `X-Play-Id` header to
track the seeded data for later cleanup. You need to set the password argument to a master password for the mock user account that is at least 8-characters. You should always use an email address with a top-level domain of example.com (see RFC 2606 — guaranteed unresolvable for more details).
```bash
curl -X POST http://localhost:5000/seed \
-H "Content-Type: application/json" \
-H "X-Play-Id: test-run-123" \
-d '{
"template": "SingleUserScene",
"arguments": {
"email": "test@example.com",
"password": "REPLACE_ME"
}
}'
```
**Response:**
```json
{
"mangleMap": {
"test@example.com": "1854b016+test@example.com",
"42bcf05d-7ad0-4e27-8b53-b3b700acc664": "42bcf05d-7ad0-4e27-8b53-b3b700acc664"
},
"result": null
}
```
The `result` contains the data returned by the scene, and `mangleMap` contains ID mappings if ID mangling is enabled.
Use the `X-Play-Id` header value to later destroy the seeded data.
### Querying Data
Send a POST request to `/query` to execute read-only queries:
```bash
curl -X POST http://localhost:5000/query \
-H "Content-Type: application/json" \
-d '{
"template": "EmergencyAccessInviteQuery",
"arguments": {
"email": "test@example.com"
}
}'
```
**Response:**
```json
["/accept-emergency?..."]
```
### Destroying Seeded Data
#### Delete by Play ID
Use the same play ID value you provided in the `X-Play-Id` header:
```bash
curl -X DELETE http://localhost:5000/seed/test-run-123
```
#### Delete Multiple by Play IDs
```bash
curl -X DELETE http://localhost:5000/seed/batch \
-H "Content-Type: application/json" \
-d '["test-run-123", "test-run-456"]'
```
#### Delete All Seeded Data
Deletes seeded data tagged with a play ID older than the provided date. Date is optional and defaults to 1 day prior to the current time of the request.
```bash
curl -X DELETE http://localhost:5000/seed \
-H "Content-Type: application/json" \
-d '"2026-03-23T10:45:47.0690009-10:00"'
```
#### PlayData is ephemeral
A scheduled job runs every fifteen minutes that deletes data tagged with a play ID older than 1 day. Any data you want to persist for an extended period of time must not be tagged with a play ID.
### Health Checks
```bash
# Check if API is alive
curl http://localhost:5000/alive
# Get API version
curl http://localhost:5000/version
```
## Creating Scenes and Queries
Scenes and queries are defined in the [Seeder](../Seeder/README.md) project. The SeederApi automatically discovers and registers all
classes implementing the scene and query interfaces.
## Configuration
The SeederApi uses the standard Bitwarden configuration system:
- `appsettings.json` - Base configuration
- `appsettings.Development.json` - Development overrides
- `dev/secrets.json` - Local secrets (database connection strings, etc.)
- User Secrets ID: `bitwarden-seeder-api`
### Required Settings
The SeederApi requires the following configuration:
- **Database Connection** - Connection string to the Bitwarden database
- **Global Settings** - Standard Bitwarden `GlobalSettings` configuration
## Play ID Tracking
Certain entities such as Users and Organizations are tracked when created by a request including a PlayId. This enables
entities to be deleted after using the PlayId.
### The X-Play-Id Header
**Important:** All seed requests should include the `X-Play-Id` header:
```bash
-H "X-Play-Id: your-unique-identifier"
```
The play ID can be any string that uniquely identifies your test run or session. Common patterns:
### How Play ID Tracking Works
When `TestPlayIdTrackingEnabled` is enabled in GlobalSettings, the `PlayIdMiddleware`
(see `src/SharedWeb/Utilities/PlayIdMiddleware.cs:7-23`) automatically:
1. **Extracts** the `X-Play-Id` header from incoming requests
2. **Sets** the play ID in the `PlayIdService` for the request scope
3. **Tracks** all entities (users, organizations, etc.) created during the request
4. **Associates** them with the play ID in the `PlayItem` table
5. **Enables** complete cleanup via the delete endpoints
This tracking works for **any API request** that includes the `X-Play-Id` header, not just SeederApi endpoints. This means
you can track entities created through:
- **Scene executions** - Data seeded via `/seed` endpoint
- **Regular API operations** - Users signing up, creating organizations, inviting members, etc.
- **Integration tests** - Any HTTP requests to the Bitwarden API during test execution
Without the `X-Play-Id` header, entities will not be tracked and cannot be cleaned up using the delete endpoints.
## Security Considerations
> [!WARNING]
> The SeederApi is intended for **development and testing environments only**. Never deploy this API to production
> environments.