chiark / gitweb /
sshkeys: Rework calling conventions of sshkeys
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 30 May 2021 11:19:30 +0000 (12:19 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 30 May 2021 12:44:07 +0000 (13:44 +0100)
We can't pass this &mut AccountsGuard and &mut PerScope since the
latter is inside the former.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/accounts.rs
src/commands.rs
src/sshkeys.rs

index e2c56d8da29cd52ea9cf6bf8d16ff476ba939672..4a40a06ac265629441bd26211ca382153ff38dc2 100644 (file)
@@ -438,8 +438,11 @@ impl AccountsGuard {
     fs::rename(&tmp, &main)?;
   }
 
-  pub fn ssh_keys_mut(&mut self) -> &mut sshkeys::Global {
-    &mut self.0.get_or_insert_with(default).ssh_keys
+  pub fn get(&self) -> &Accounts {
+    self.0.as_ref().expect("loaded")
+  }
+  pub fn get_mut(&mut self) -> &mut Accounts {
+    self.0.as_mut().expect("loaded")
   }
 }
 
index c3cc997ae0af804f4fb05ecb836aefc28fc7df28..a19bf5fc1c5bae0e26457b77f4c6eafb7b9b4a77 100644 (file)
@@ -258,6 +258,7 @@ pub enum MgmtError {
   #[error("game contains invalid UTF-8")]            GameSpecInvalidData,
   #[error("idle timeout waiting for mgmt command")]  IdleTimeout,
   #[error("upload took too long (timed out)")]       UploadTimeout,
+  #[error("ssh keys are only for main subaccount")]  NoSshKeysForSubaccount,
   #[error("ssh key not found")]                      SshKeyNotFound,
   #[error("ssh key id default, ie invalid")]         InvalidSshKeyId,
   #[error("ssh key invalid: {0}")] InvalidSshKey(#[from] sshkeys::KeyError),
index 255dedec4101f24f6bbdd6d5d827e6289e7d3d2e..fd45bf7aef8fffa4bf766fd2384583ae577ee697 100644 (file)
@@ -172,9 +172,31 @@ pub struct MgmtKeyReport {
   problem: Option<KeyError>,
 }
 
+macro_rules! def_pskeys_get {
+  ($trait:ident, $f:ident, $get:ident, $($mut:tt)?) => {
+    #[ext(name=$trait)]
+    impl DenseSlotMap<AccountId, AccountRecord> {
+      #[throws(MgmtError)]
+      fn $f(& $($mut)? self, acctid: AccountId) -> & $($mut)? PerScope {
+        let record = self.$get(acctid).ok_or(AccountNotFound)?;
+        if ! record.account.subaccount.is_empty() {
+          throw!(ME::NoSshKeysForSubaccount)
+        }
+        & $($mut)? record.ssh_keys
+      }
+    }
+  }
+}
+
+def_pskeys_get!{ RecordsExtImm, pskeys_get, get    ,     }
+def_pskeys_get!{ RecordsExtMut, pskeys_mut, get_mut, mut }
+
 impl AccountsGuard {
-  pub fn keys(&mut self, ps: &PerScope) -> Vec<MgmtKeyReport> {
-    let gl = self.ssh_keys_mut();
+  #[throws(MgmtError)]
+  pub fn sshkeys_report(&self, acctid: AccountId) -> Vec<MgmtKeyReport> {
+    let accounts = self.get();
+    let gl = &accounts.ssh_keys;
+    let ps = &accounts.records.pskeys_get(acctid)?;
     let dirty_error =
       if gl.authkeys_dirty { Some(KeyError::Dirty) }
       else { None };
@@ -195,11 +217,13 @@ impl AccountsGuard {
 
   // not a good idea to speicfy a problem, but "whatever"
   #[throws(ME)]
-  pub fn add_key(&mut self, ps: &mut PerScope,
-                 new_akl: AuthkeysLine) -> (usize, Id) {
+  pub fn sshkeys_add(&mut self, acctid: AccountId,
+                     new_akl: AuthkeysLine) -> (usize, Id) {
+    let accounts = self.get_mut();
+    let gl = &mut accounts.ssh_keys;
+    let ps = accounts.records.pskeys_mut(acctid)?;
     let (data, comment) = new_akl.parse()?;
     let fp = data.fingerprint().map_err(KeyError::from)?;
-    let gl = self.ssh_keys_mut();
     let fp = Arc::new(fp);
     let _ = gl.fps();
     let fpe = gl.fps.as_mut().unwrap().entry(fp.clone());
@@ -236,15 +260,17 @@ impl AccountsGuard {
     // UNSAVED
     self.save_accounts_now()?;
     // BROKEN
-    self.ssh_keys_mut().rewrite_authorized_keys()?;
+    self.get_mut().ssh_keys.rewrite_authorized_keys()?;
     // PRESENT
     (index, id)
   }
 
   #[throws(ME)]
-  pub fn remove_key(&mut self, ps: &mut PerScope,
+  pub fn remove_key(&mut self, acctid: AccountId,
                     index: usize, id: Id) {
-    let gl = self.ssh_keys_mut();
+    let accounts = self.get_mut();
+    let gl = &mut accounts.ssh_keys;
+    let ps = accounts.records.pskeys_mut(acctid)?;
     if id == default() {
       throw!(ME::InvalidSshKeyId);
     }
@@ -265,7 +291,12 @@ impl AccountsGuard {
     let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(
       || self.save_accounts_now()
     ));
-    let gl = self.ssh_keys_mut();
+
+    // Must re-borrow everything since save_accounts_now needed a
+    // reference to all of it.
+    let accounts = self.get_mut();
+    let gl = &mut accounts.ssh_keys;
+    let ps = accounts.records.pskeys_mut(acctid).expect("aargh!");
     let key = gl.keys.get_mut(id).expect("aargh!");
 
     if ! matches!(r, Ok(Ok(()))) {