4.5 KiB
| title | status | type | priority | created_at | updated_at |
|---|---|---|---|---|---|
| Implement auth code session storage — utility module and AuthModal pre-fill integration | completed | task | high | 2026-03-10T23:32:07Z | 2026-03-10T23:32:07Z |
Chosen strategy: session storage per quote ID. The code is stored in the browser's
sessionStorage under the key auth_code_{id} when first entered. It is automatically cleared
when the tab closes. No explicit clear-on-delete is required (session storage is short-lived by
design), but it is good practice and should be included.
Options considered:
- localStorage: ruled out — indefinite persistence is unnecessary; the app tells users to store the code externally anyway, and localStorage has a wider XSS exposure window.
- Component state only: ruled out — code is lost on any page navigation or reload, making the edit/delete flow unusable in practice.
Create a module with three public functions that wrap the browser's sessionStorage API:
use web_sys::window;
/// Retrieve the stored auth code for a given quote ID, if any.
pub fn get_auth_code(quote_id: &str) -> Option<String> {
let storage = window()?.session_storage().ok()??;
storage.get_item(&format!("auth_code_{quote_id}")).ok()?
}
/// Persist the auth code for a quote ID in sessionStorage.
pub fn set_auth_code(quote_id: &str, code: &str) {
if let Some(Ok(storage)) = window().map(|w| w.session_storage()) {
if let Some(storage) = storage {
let _ = storage.set_item(&format!("auth_code_{quote_id}"), code);
}
}
}
/// Remove the auth code for a quote ID from sessionStorage (call after DELETE).
pub fn clear_auth_code(quote_id: &str) {
if let Some(Ok(storage)) = window().map(|w| w.session_storage()) {
if let Some(storage) = storage {
let _ = storage.remove_item(&format!("auth_code_{quote_id}"));
}
}
}
Expose this module from the UI binary root: add mod storage; to src/bin/ui/main.rs.
Part 2 — AuthModal pre-fill
Update the AuthModal component (ticket f850c6) to accept an initial_value: Option<String>
prop. Pre-populate the <input> value from this prop when the modal opens. The parent
component is responsible for reading from storage and passing the value in.
#[derive(Properties, PartialEq)]
pub struct AuthModalProps {
pub on_submit: Callback<String>,
pub on_cancel: Callback<()>,
pub initial_value: Option<String>, // pre-fill if auth code is already stored
}
Part 3 — SingleQuotePage integration
In the SingleQuotePage (or whichever component renders edit/delete for a quote), integrate
storage around the AuthModal:
- Before opening the modal: read
storage::get_auth_code("e.id)and pass it asinitial_valuetoAuthModal. - After a successful edit (POST /api/quotes/:id returns 200): call
storage::set_auth_code("e.id, &submitted_code). - After a successful delete (DELETE /api/quotes/:id returns 204): call
storage::clear_auth_code("e.id). - If the API returns 403 (wrong code): do NOT store the code; clear any existing stored value
with
storage::clear_auth_code("e.id)so a stale code is not re-offered.
quotesdb/ui