chiark / gitweb /
wip new account etc., adding acctid etc.
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 24 Oct 2020 11:50:29 +0000 (12:50 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 24 Oct 2020 11:50:29 +0000 (12:50 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/accounts.rs
src/bin/daemon-otter.rs
src/global.rs
src/imports.rs
src/session.rs

index 00cd76a9423c165530211e2a2752dd4223967422..7acaf7a63a72c418a6ad99de0c48193fe0d4b1ef 100644 (file)
@@ -137,7 +137,7 @@ impl FromStr for AccountName {
   }
 }
 
-#[derive(Serialize,Deserialize)]
+#[derive(Serialize,Deserialize,Debug)]
 pub struct AccountRecord {
   pub nick: String,
   pub timezone: String,
@@ -168,21 +168,64 @@ pub fn save_accounts_now() -> Result<(), InternalError> {
   panic!("xxx")
 }
 
+#[derive(Default,Debug)]
+struct LookupHelper {
+  acctid_r: Option<AccountId>,
+}
+
+impl LookupHelper {
+  #[throws(as Option)]
+  fn get(&mut self, accounts: &Accounts, account: &AccountName) -> AccountId {
+    let acctid = *accounts.names.get(account)?;
+    self.acctid_r = Some(acctid);
+    acctid
+  }
+/*
+  fn finish<T, E>(self) -> impl FnOnce(<T,E>) -> Option<(T, AccountId)>
+  {
+    move |got: Result<T,E>| Some((got.ok()?, self.acctid_r?))
+  }
+*/
+  fn wrap<T, E>(self, got: Result<T,E>) -> Option<(T, AccountId)> {
+    Some((got.ok()?, self.acctid_r?))
+  }
+}
+
 impl AccountRecord {
+  pub fn bulk_check(names: &[&AccountName]) -> Vec<Option<AccountId>> {
+    let accounts = ACCOUNTS.read();
+    names.iter().map(|&name|{
+      accounts.as_ref()?.names.get(name).map(|&acctid| acctid)
+    }).collect()
+  }
+
   pub fn lookup(account: &AccountName,  _: Authorisation<AccountName>)
-                -> Option<MappedRwLockReadGuard<'static, AccountRecord>> {
-    RwLockReadGuard::try_map(
-      ACCOUNTS.read(),
-      |accounts| accounts.as_ref()?.get(account)
-    ).ok()
+                -> Option<(MappedRwLockReadGuard<'static, AccountRecord>,
+                           AccountId)>
+  {
+    let mut helper : LookupHelper = default();
+    helper.wrap(
+      RwLockReadGuard::try_map(ACCOUNTS.read(), |accounts| {
+        let accounts = accounts.as_ref()?;
+        let acctid = helper.get(accounts, account)?;
+        accounts.records.get(acctid)
+      })
+    )
   }
-  pub fn lookup_mut_caller_must_save(account: &AccountName,
-                                      _auth: Authorisation<AccountName>)
-            -> Option<MappedRwLockWriteGuard<'static, AccountRecord>> {
-    RwLockWriteGuard::try_map(
-      ACCOUNTS.write(),
-      |accounts| accounts.as_mut()?.get_mut(account)
-    ).ok()
+
+  pub fn lookup_mut_caller_must_save
+    ( account: &AccountName, _auth: Authorisation<AccountName>)
+    -> Option<(MappedRwLockWriteGuard<'static, AccountRecord>,
+               AccountId)>
+  {
+    let mut helper : LookupHelper = default();
+    helper.wrap(
+      RwLockWriteGuard::try_map(ACCOUNTS.write(), |accounts| {
+        let accounts = accounts.as_mut()?;
+        let acctid = helper.get(accounts, account)?;
+        accounts.records.get_mut(acctid)
+      })
+    )
   }
 
   #[throws(MgmtError)]
@@ -190,18 +233,22 @@ impl AccountRecord {
                               auth: Authorisation<AccountName>,
                               f: F)
                               -> Result<T, (InternalError, T)>
-  where F: FnOnce(&mut AccountRecord) -> T
+  where F: FnOnce(&mut AccountRecord, AccountId) -> T
   {
     let entry = AccountRecord::lookup_mut_caller_must_save(account, auth)
       .ok_or(MgmtError::AccountNotFound)?;
     let old_access = entry.access.clone();
     let output = f(entry);
     let mut ok = true;
-    if ! Arc::ptr_eq(old_access, entry.access) {
-// xxx actually do this
+    if_chain!{
+      if let Some(entry) = entry;
+      if Arc::ptr_eq(old_access, entry.access);
+      then {
+      // xxx actually do this
 //      invalidate_all_tokens_for_account(accid)
 //        .dont_just_questionmark
-    }
+      }
+    };
     let ok = if entry.is_some() { save_accounts_now() } else { Ok(()) };
     match ok {
       Ok(()) => Ok(output),
index 3ab2fc983d434e20d010a5e52339da06a96e3f07..97d5faa2b6d4d3e3bf60f3e35b9b7f6383802ada 100644 (file)
@@ -118,6 +118,7 @@ fn main() {
 
   shapelib::load()?;
 
+  load_accounts()?;
   load_games()?;
 
   let cl = CommandListener::new()?;
index 912844c4fa7892c7259aeedb1cddebb4468faeb3..8676f1788b13228ca5e7771de81c85de79b6deb6 100644 (file)
@@ -164,7 +164,7 @@ pub struct TokenRegistry<Id: AccessId> {
 pub struct InstanceAccessDetails<Id> {
   pub gref : InstanceRef,
   pub ident : Id,
-  pub accid : AccountId,
+  pub acctid : AccountId,
 }
 
 #[derive(Clone,Debug)]
@@ -571,7 +571,7 @@ impl InstanceGuard<'_> {
       .ok_or(MgmtError::PlayerNotFound)?
       .pst;
 
-    let access = AccountRecord::with_entry_mut(
+    let (access, acctid) = AccountRecord::with_entry_mut(
       &pst.account, authorised,
       |acct, acctid|
     {
@@ -585,7 +585,7 @@ impl InstanceGuard<'_> {
         })
         .latest = now;
       acct.expire_tokens_revealed();
-      Ok::<_,MgmtError>(access.clone())
+      Ok::<_,MgmtError>((access.clone(), acctid))
     })?.map_err(|(e,_)|e)??;
 
     if reset {
@@ -604,7 +604,8 @@ impl InstanceGuard<'_> {
         
       let iad = InstanceAccessDetails {
         gref : self.gref.clone(),
-        ident : player
+        ident : player,
+        acctid
       };
       self.token_register(token.clone(), iad);
 
@@ -877,9 +878,18 @@ impl InstanceGuard<'_> {
     }
 
     let name = Arc::new(name);
-    tokens_players.retain(
-      |&(_,player)| gs.players.contains_key(player)
-    );
+    let (tokens_players, acctids_players) = {
+      let mut tokens = Vec::with_capacity(tokens_players.len());
+      let mut acctnames = Vec::with_capacity(tokens_players.len());
+      for (token, player) in tokens_players { if_chain! {
+        if let Some(name) = gs.players.get(player);
+        then {
+          tokens.push((token, player));
+          acctnames.push(name);
+        }
+      }}
+      (tokens, AccountRecord::bulk_check(&acctnames))
+    };
 
     let g = Instance {
       gs, iplayers,
@@ -902,13 +912,18 @@ impl InstanceGuard<'_> {
       g.tokens_players.tr.insert(RawToken(token.clone()));
     }
     let mut global = GLOBAL.players.write().unwrap();
-    for (token, player) in tokens_players.drain(0..) {
+    for ((token, player), acctid) in
+      tokens_players.drain(0..)
+      .zip(acctids_players)
+    { if_chain!{
+      if let Some(acctid) = acctid;
       let iad = InstanceAccessDetails {
+        acctid,
         gref : gref.clone(),
         ident : player,
       };
-      global.insert(RawToken(token), iad);
-    }
+      then { global.insert(RawToken(token), iad); }
+    } }
     drop(global);
     drop(g);
     GLOBAL.games.write().unwrap().insert(name.clone(), gref.clone());
index 4dc5b5cd9cbbcc0703088e73c52dd50f695ace92..a673c5d6d129a2dac35166d65bcb3f6d4483791e 100644 (file)
@@ -108,6 +108,8 @@ pub use ordered_float::OrderedFloat;
 
 pub use either::{Either,Left,Right};
 
+pub use if_chain::if_chain;
+
 pub use crate::global::*;
 pub use crate::gamestate::*;
 pub use crate::pieces::*;
index 188f210b0ff39e5aea5e2a638f14d23e98f0719f..b647d742796c6af12f40616602db532ec27855b9 100644 (file)
@@ -65,6 +65,7 @@ fn session(form : Json<SessionForm>) -> Result<Template,OE> {
     let ciad = InstanceAccessDetails {
       gref : iad.gref.clone(),
       ident : client,
+      acctid: iad.acctid,
     };
     let ctoken = record_token(&mut ig, ciad)?;
     let ig = &mut *ig;