Add self-service transitions, authorized by item possession not group membership
Deploy / deploy (push) Successful in 33s
Deploy / deploy (push) Successful in 33s
New Alternative.self_transition: like ResourceSpec.transitions, but for an anonymous visitor holding one specific item's own chain hash (from a ?chain= link, the same reference /subscribed?chain=... already carries) rather than a signed-in owner browsing a whole bucket. email is a second factor checked against the stored item, not the lookup key - defense in depth against a leaked/guessed chain hash alone. AlternativeCard renders it as a single confirm button when both ?chain= and ?email= are present; QuestionView hides the alternative entirely otherwise, rather than showing a dead card with nothing to click. Powers /subscribed's new "Unsubscribe" alternative, which the newsletter's own recipient links now carry - no email lookup needed, just the same chain_hash the subscription itself already produced.
This commit is contained in:
@@ -58,6 +58,26 @@ pub struct Alternative {
|
||||
/// silently break if the wording changes later.
|
||||
#[serde(default)]
|
||||
pub record_as: Option<String>,
|
||||
/// A transition anyone holding the *right item's own reference* can
|
||||
/// fire - not gated by `requires_group` like `ResourceSpec.transitions`,
|
||||
/// which is for signed-in owners browsing a whole bucket. This is
|
||||
/// the opposite shape: an anonymous visitor who already holds one
|
||||
/// specific chain hash (from a `?chain=` link - see `chain.rs`,
|
||||
/// the same reference `/subscribed?chain=...` already carries) may
|
||||
/// transition *that one item*, and only that one, without ever
|
||||
/// being able to enumerate or touch anyone else's. `email` is a
|
||||
/// second factor checked against the stored item's own `email`
|
||||
/// response field - not the lookup key, just cheap defense in depth
|
||||
/// against a leaked/guessed chain hash alone being sufficient.
|
||||
#[serde(default)]
|
||||
pub self_transition: Option<SelfTransition>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct SelfTransition {
|
||||
pub bucket: String,
|
||||
pub to: String,
|
||||
pub label: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
|
||||
Reference in New Issue
Block a user