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.
100 lines
2.8 KiB
Markdown
100 lines
2.8 KiB
Markdown
+++
|
|
title = "quotesdb/api: GET /api/status public endpoint"
|
|
priority = 6
|
|
status = "done"
|
|
ticket_type = "feature"
|
|
dependencies = ["69a2c5"]
|
|
+++
|
|
## 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
|
|
``` |