spaces: a member wears a key minted for that room alone, so a roster stops naming personas
This commit is contained in:
1 parent
b3c121fa94
commit
67e52697b2
6 files changed
+462
-58
No files matched your search
@@ -271,7 +271,24 @@ async fn pinned_of(app: &tauri::AppHandle, space_owner_b58: &str, space_b58: &st
|
||||
|
||||
type Current = (pl::ManifestV1, [u8; 32]);
|
||||
|
||||
fn view_of(app: &tauri::AppHandle, pin: &Pinned, current: Option<&Current>, board: &pr::BoardState, me: &[u8; 32], reachable: bool) -> BoardView {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn view_of(
|
||||
app: &tauri::AppHandle,
|
||||
pin: &Pinned,
|
||||
current: Option<&Current>,
|
||||
board: &pr::BoardState,
|
||||
me: &[u8; 32],
|
||||
worn: &[u8; 32],
|
||||
space: (&str, &str),
|
||||
reachable: bool,
|
||||
) -> BoardView {
|
||||
// A room key has a name only on the device that seated it — the Space's
|
||||
// owner. Everyone else sees the key, which is what unlinkable means.
|
||||
let name_of = |k: &[u8; 32]| -> Option<String> {
|
||||
let b = b58(k);
|
||||
let persona = spaces::persona_behind(app, space.0, space.1, &b).unwrap_or(b);
|
||||
slsk_link::username_for_key(app, &persona)
|
||||
};
|
||||
let entries: Vec<BoardEntry> = current
|
||||
.map(|(m, _)| {
|
||||
m.entries
|
||||
@@ -306,8 +323,8 @@ fn view_of(app: &tauri::AppHandle, pin: &Pinned, current: Option<&Current>, boar
|
||||
.map(|p| ProposalView {
|
||||
id: b58(&p.proposal_id),
|
||||
author: b58(&p.author),
|
||||
username: slsk_link::username_for_key(app, &b58(&p.author)),
|
||||
is_me: &p.author == me,
|
||||
username: name_of(&p.author),
|
||||
is_me: &p.author == worn,
|
||||
created_at: p.created_at,
|
||||
note: p.note.clone(),
|
||||
base: b58(&p.base_revision_hash),
|
||||
@@ -374,10 +391,10 @@ fn view_of(app: &tauri::AppHandle, pin: &Pinned, current: Option<&Current>, boar
|
||||
epoch: board.authority.as_ref().map(|a| a.epoch).unwrap_or(0),
|
||||
contributors: roster
|
||||
.iter()
|
||||
.map(|k| ContributorView { key: b58(k), username: slsk_link::username_for_key(app, &b58(k)), is_me: k == me })
|
||||
.map(|k| ContributorView { key: b58(k), username: name_of(k), is_me: k == worn })
|
||||
.collect(),
|
||||
i_am_owner: &pin.owner == me,
|
||||
can_propose: reachable && current.is_some() && roster.contains(me),
|
||||
can_propose: reachable && current.is_some() && roster.contains(worn),
|
||||
proposals,
|
||||
decisions,
|
||||
pending_mine: board.proposals.iter().filter(|p| &p.author == me).count() as u32,
|
||||
@@ -417,7 +434,8 @@ pub async fn open(app: &tauri::AppHandle, space_owner_b58: &str, space_b58: &str
|
||||
log::info!("proposals: roster epoch {} for board {}", epoch, b58(&pin.uuid));
|
||||
}
|
||||
}
|
||||
Ok(view_of(app, &pin, current.as_ref(), &board, &me, exists))
|
||||
let (worn, _) = spaces::worn_identity(app, space_owner_b58, space_b58, &me);
|
||||
Ok(view_of(app, &pin, current.as_ref(), &board, &me, &worn, (space_owner_b58, space_b58), exists))
|
||||
}
|
||||
|
||||
/// A member proposes: the ops are dry-run against the exact base first, so
|
||||
@@ -441,8 +459,11 @@ pub async fn propose(app: &tauri::AppHandle, space_owner_b58: &str, space_b58: &
|
||||
if !exists {
|
||||
return Err("the owner has not opened this board yet".into());
|
||||
}
|
||||
// The board's roster is the Space's roster, so we appear on it as the key
|
||||
// we wear there — a room-local one unless the Space is ours.
|
||||
let (worn, room) = spaces::worn_identity(app, space_owner_b58, space_b58, &me);
|
||||
let auth = board.authority.as_ref().ok_or("the board has no roster yet")?;
|
||||
if !auth.contributors.contains(&me) {
|
||||
if !auth.contributors.contains(&worn) {
|
||||
return Err("you are not on this board's roster — the owner refreshes it from the Space's members".into());
|
||||
}
|
||||
let mut fresh: BTreeMap<String, [u8; 16]> = BTreeMap::new();
|
||||
@@ -492,7 +513,7 @@ pub async fn propose(app: &tauri::AppHandle, space_owner_b58: &str, space_b58: &
|
||||
}
|
||||
let mut p = pr::Proposal {
|
||||
proposal_id: rand16(),
|
||||
author: me,
|
||||
author: worn,
|
||||
authority_epoch: auth.epoch,
|
||||
base_revision_hash: hash,
|
||||
ops: pops,
|
||||
@@ -501,7 +522,10 @@ pub async fn propose(app: &tauri::AppHandle, space_owner_b58: &str, space_b58: &
|
||||
sig: vec![],
|
||||
};
|
||||
pr::apply_proposal(&manifest, &hash, &p).map_err(|e| e.to_string())?;
|
||||
p.sig = sign(app, pr::sign_payload(&pr::proposal_sig_body(&p))).await?;
|
||||
p.sig = match room {
|
||||
Some(secret) => persona_state::sign_local(pr::SIGN_DOMAIN, &secret, &pr::proposal_sig_body(&p)),
|
||||
None => sign(app, pr::sign_payload(&pr::proposal_sig_body(&p))).await?,
|
||||
};
|
||||
if !pr::proposal_valid(&p) {
|
||||
return Err("the proposal did not validate (a size or field cap)".into());
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user