You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vibed/quotesdb/.beans/quotesdb-um1y--quotesdbapi-...

106 lines
2.8 KiB
Markdown

---
# quotesdb-um1y
title: 'quotesdb/api: GET /api/status public endpoint'
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:32:06Z
updated_at: 2026-03-10T23:32:13Z
blocked_by:
- quotesdb-04cw
---
## GET /api/status public endpoint
Add a public status endpoint that exposes whether submissions are currently locked. The UI calls this on mount for both the /submit and /admin pages.
---
## Files to modify
- `src/bin/api/db/mod.rs` — add `get_submissions_locked` and `set_submissions_locked` to the `QuoteRepository` trait
- `src/bin/api/db/d1.rs` — implement the two new trait methods for the D1 backend; seed `submissions_locked = "0"` alongside `admin_auth_code` in the startup migration if not already present
- `src/bin/api/db/native.rs` — implement the two new trait methods for the native/SQLite backend
- `src/bin/api/handlers/mod.rs` (or a new `src/bin/api/handlers/status.rs`) — add the `get_status` handler
- `src/bin/api/main.rs` — register the new route
---
## Database
The `admin_config` key/value table gains a second row. Seed it on startup (alongside `admin_auth_code`) if it does not already exist:
```sql
INSERT OR IGNORE INTO admin_config (key, value) VALUES ('submissions_locked', '0');
```
---
## New trait methods (src/bin/api/db/mod.rs)
Add to the `QuoteRepository` trait:
```rust
/// Return whether submissions are currently locked.
async fn get_submissions_locked(&self) -> Result<bool, DbError>;
/// Set the submissions lock state.
async fn set_submissions_locked(&self, locked: bool) -> Result<(), DbError>;
```
Both implementations read/write the `submissions_locked` key in `admin_config`, treating `"1"` as `true` and anything else as `false`.
---
## Handler
Add to the handlers module:
```rust
/// GET /api/status — returns current submission lock state; requires no auth.
pub async fn get_status(State(repo): State<Arc<dyn QuoteRepository>>) -> impl IntoResponse {
match repo.get_submissions_locked().await {
Ok(locked) => Json(json!({ "submissions_locked": locked })).into_response(),
Err(_) => StatusCode::INTERNAL_SERVER_ERROR.into_response(),
}
}
```
---
## Route registration (src/bin/api/main.rs)
Register before the quotes router:
```rust
.route("/api/status", get(handlers::get_status))
```
---
## Tests
In `src/bin/api/handlers/` (or the relevant test module), add unit tests covering:
- `GET /api/status` returns `200` with `{ "submissions_locked": false }` when the DB value is `"0"`
- `GET /api/status` returns `200` with `{ "submissions_locked": true }` when the DB value is `"1"`
- `get_submissions_locked` returns `false` for missing key (graceful default)
Use a mock or in-memory SQLite repo for all handler tests.
---
## Validation
```sh
cargo fmt && cargo check && cargo clippy && cargo test
```
---
## Commit
```
feat(quotesdb): GET /api/status public endpoint
```